[Swfdec-commits] 11 commits - swfdec-gtk/swfdec_playback_alsa.c swfdec/Makefile.am swfdec/swfdec_as_interpret.c swfdec/swfdec_audio_decoder_adpcm.c swfdec/swfdec_audio_decoder_adpcm.h swfdec/swfdec_audio_decoder.c swfdec/swfdec_audio_decoder_gst.c swfdec/swfdec_audio_decoder_gst.h swfdec/swfdec_audio_decoder.h swfdec/swfdec_audio_decoder_uncompressed.c swfdec/swfdec_audio_decoder_uncompressed.h swfdec/swfdec_audio_event.c swfdec/swfdec_audio_flv.c swfdec/swfdec_audio_flv.h swfdec/swfdec_audio_stream.c swfdec/swfdec_audio_stream.h swfdec/swfdec_audio_swf_stream.c swfdec/swfdec_audio_swf_stream.h swfdec/swfdec_codec_adpcm.c swfdec/swfdec_codec_audio.c swfdec/swfdec_codec_audio.h swfdec/swfdec_codec_gst.c swfdec/swfdec_codec_gst.h swfdec/swfdec_decoder.c swfdec/swfdec_flv_decoder.c swfdec/swfdec_flv_decoder.h swfdec/swfdec_internal.h swfdec/swfdec_movie_clip_loader.c swfdec/swfdec_resource.c swfdec/swfdec_resource.h swfdec/swfdec_sound.c swfdec/swfdec_sound.h swfdec/swfdec_sprite.c swfdec/swfdec_sprite.h swfdec/swfdec_sprite_movie.c swfdec/swfdec_sprite_movie.h swfdec/swfdec_system_as.c swfdec/swfdec_tag.c tools/dump.c tools/swfdec-extract.c
Benjamin Otte
company at kemper.freedesktop.org
Thu May 29 07:18:31 PDT 2008
swfdec-gtk/swfdec_playback_alsa.c | 60 +++--
swfdec/Makefile.am | 19 +
swfdec/swfdec_as_interpret.c | 10
swfdec/swfdec_audio_decoder.c | 241 ++++++++++++++++++++++
swfdec/swfdec_audio_decoder.h | 92 ++++++++
swfdec/swfdec_audio_decoder_adpcm.c | 199 ++++++++++++++++++
swfdec/swfdec_audio_decoder_adpcm.h | 54 +++++
swfdec/swfdec_audio_decoder_gst.c | 199 ++++++++++++++++++
swfdec/swfdec_audio_decoder_gst.h | 61 +++++
swfdec/swfdec_audio_decoder_uncompressed.c | 145 +++++++++++++
swfdec/swfdec_audio_decoder_uncompressed.h | 54 +++++
swfdec/swfdec_audio_event.c | 1
swfdec/swfdec_audio_flv.c | 4
swfdec/swfdec_audio_flv.h | 1
swfdec/swfdec_audio_stream.c | 187 ++++++++---------
swfdec/swfdec_audio_stream.h | 26 +-
swfdec/swfdec_audio_swf_stream.c | 216 ++++++++++++++++++++
swfdec/swfdec_audio_swf_stream.h | 59 +++++
swfdec/swfdec_codec_adpcm.c | 203 ------------------
swfdec/swfdec_codec_audio.c | 310 -----------------------------
swfdec/swfdec_codec_audio.h | 58 -----
swfdec/swfdec_codec_gst.c | 254 ++++-------------------
swfdec/swfdec_codec_gst.h | 59 +++++
swfdec/swfdec_decoder.c | 4
swfdec/swfdec_flv_decoder.c | 1
swfdec/swfdec_flv_decoder.h | 2
swfdec/swfdec_internal.h | 13 -
swfdec/swfdec_movie_clip_loader.c | 17 -
swfdec/swfdec_resource.c | 199 +++++++++++-------
swfdec/swfdec_resource.h | 12 -
swfdec/swfdec_sound.c | 100 ---------
swfdec/swfdec_sound.h | 3
swfdec/swfdec_sprite.c | 49 ----
swfdec/swfdec_sprite.h | 11 -
swfdec/swfdec_sprite_movie.c | 94 ++------
swfdec/swfdec_sprite_movie.h | 2
swfdec/swfdec_system_as.c | 2
swfdec/swfdec_tag.c | 36 ++-
tools/dump.c | 26 --
tools/swfdec-extract.c | 18 -
40 files changed, 1804 insertions(+), 1297 deletions(-)
New commits:
commit c88a4bd5805ffd0d3775c3e3dea45c3a9e51f3d1
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 29 16:17:36 2008 +0200
rework resource loading to keep the target movie at hand
makes MovieClipLoader work when using it on movies that have a dot in
their name.
diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index a6d7044..534a86a 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -1144,7 +1144,7 @@ swfdec_action_get_url (SwfdecAsContext *cx, guint action, const guint8 *data, gu
SWFDEC_ERROR ("GetURL without a SwfdecPlayer");
} else {
swfdec_resource_load (SWFDEC_PLAYER (cx), target, url,
- SWFDEC_LOADER_REQUEST_DEFAULT, NULL, NULL, FALSE);
+ SWFDEC_LOADER_REQUEST_DEFAULT, NULL);
}
g_free (url);
g_free (target);
@@ -1184,7 +1184,6 @@ swfdec_action_get_url2 (SwfdecAsContext *cx, guint action, const guint8 *data, g
SWFDEC_FIXME ("encode variables");
}
- target = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1));
url = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 2));
if (!SWFDEC_IS_PLAYER (cx)) {
@@ -1192,13 +1191,18 @@ swfdec_action_get_url2 (SwfdecAsContext *cx, guint action, const guint8 *data, g
} else if (variables) {
SwfdecMovie *movie;
+ target = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1));
movie = swfdec_player_get_movie_from_string (SWFDEC_PLAYER (cx), target);
if (movie != NULL) {
swfdec_load_object_create (SWFDEC_AS_OBJECT (movie), url, method, NULL, NULL,
swfdec_as_interpret_load_variables_on_finish);
}
+ } else if (internal) {
+ swfdec_resource_load_movie (SWFDEC_PLAYER (cx), swfdec_as_stack_peek (cx, 1),
+ url, method, NULL, NULL);
} else {
- swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, method, NULL, NULL, internal);
+ target = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 1));
+ swfdec_resource_load (SWFDEC_PLAYER (cx), target, url, method, NULL);
}
swfdec_as_stack_pop_n (cx, 2);
diff --git a/swfdec/swfdec_movie_clip_loader.c b/swfdec/swfdec_movie_clip_loader.c
index 77d8704..2c6d5e4 100644
--- a/swfdec/swfdec_movie_clip_loader.c
+++ b/swfdec/swfdec_movie_clip_loader.c
@@ -70,12 +70,13 @@ swfdec_movie_clip_loader_loadClip (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
{
SwfdecMovieClipLoader *loader;
- const char *url, *target;
+ const char *url;
+ SwfdecAsValue target;
- SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE_CLIP_LOADER, &loader, "ss", &url, &target);
+ SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE_CLIP_LOADER, &loader, "sv", &url, &target);
- swfdec_resource_load (SWFDEC_PLAYER (cx), target, url,
- SWFDEC_LOADER_REQUEST_DEFAULT, NULL, loader, TRUE);
+ swfdec_resource_load_movie (SWFDEC_PLAYER (cx), &target, url,
+ SWFDEC_LOADER_REQUEST_DEFAULT, NULL, loader);
}
SWFDEC_AS_NATIVE (112, 102, swfdec_movie_clip_loader_unloadClip)
@@ -84,12 +85,12 @@ swfdec_movie_clip_loader_unloadClip (SwfdecAsContext *cx, SwfdecAsObject *object
guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
{
SwfdecMovieClipLoader *loader;
- const char *target;
+ SwfdecAsValue target;
- SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE_CLIP_LOADER, &loader, "s", &target);
+ SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE_CLIP_LOADER, &loader, "v", &target);
- swfdec_resource_load (SWFDEC_PLAYER (cx), target, "",
- SWFDEC_LOADER_REQUEST_DEFAULT, NULL, loader, TRUE);
+ swfdec_resource_load_movie (SWFDEC_PLAYER (cx), &target, "",
+ SWFDEC_LOADER_REQUEST_DEFAULT, NULL, loader);
}
SWFDEC_AS_NATIVE (112, 101, swfdec_movie_clip_loader_getProgress)
diff --git a/swfdec/swfdec_resource.c b/swfdec/swfdec_resource.c
index deb7d91..7b90528 100644
--- a/swfdec/swfdec_resource.c
+++ b/swfdec/swfdec_resource.c
@@ -111,28 +111,34 @@ swfdec_resource_emit_signal (SwfdecResource *resource, const char *name, gboolea
SwfdecAsValue *args, guint n_args)
{
SwfdecAsContext *cx;
- SwfdecAsObject *movie;
+ SwfdecMovie *movie;
guint skip = progress ? 4 : 2;
SwfdecAsValue vals[n_args + skip];
if (resource->clip_loader == NULL)
return;
cx = SWFDEC_AS_OBJECT (resource->clip_loader)->context;
- g_assert (resource->target);
- movie = swfdec_action_lookup_object (cx, SWFDEC_PLAYER (cx)->priv->roots->data,
- resource->target, resource->target + strlen (resource->target));
- if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
+ /* This feels wrong. Why do we resolve here by real name? */
+ if (resource->target)
+ movie = swfdec_movie_get_by_name (resource->target->parent, resource->target->name, FALSE);
+ else
+ movie = NULL;
+ if (movie == NULL && resource->movie != NULL) {
SWFDEC_DEBUG ("no movie, not emitting signal");
return;
}
if (name == SWFDEC_AS_STR_onLoadInit &&
- movie != SWFDEC_AS_OBJECT (resource->movie)) {
+ movie != SWFDEC_MOVIE (resource->movie)) {
SWFDEC_INFO ("not emitting onLoadInit - the movie is different");
return;
}
SWFDEC_AS_VALUE_SET_STRING (&vals[0], name);
- SWFDEC_AS_VALUE_SET_OBJECT (&vals[1], movie);
+ if (movie) {
+ SWFDEC_AS_VALUE_SET_OBJECT (&vals[1], SWFDEC_AS_OBJECT (movie));
+ } else {
+ SWFDEC_AS_VALUE_SET_UNDEFINED (&vals[1]);
+ }
if (progress) {
SwfdecResource *res;
@@ -197,40 +203,6 @@ swfdec_resource_replace_movie (SwfdecSpriteMovie *movie, SwfdecResource *resourc
return SWFDEC_SPRITE_MOVIE (copy);
}
-static gboolean
-swfdec_resource_create_movie (SwfdecResource *resource)
-{
- SwfdecPlayer *player;
- SwfdecSpriteMovie *movie;
- int level = -1;
-
- if (resource->movie)
- return TRUE;
- player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource)->context);
- movie = (SwfdecSpriteMovie *) swfdec_action_lookup_object (SWFDEC_AS_CONTEXT (player),
- player->priv->roots->data, resource->target, resource->target + strlen (resource->target));
- if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
- level = swfdec_player_get_level (player, resource->target);
- if (level < 0) {
- SWFDEC_WARNING ("%s does not reference a movie, not loading %s", resource->target,
- swfdec_url_get_url (swfdec_loader_get_url (resource->loader)));
- swfdec_stream_close (SWFDEC_STREAM (resource->loader));
- swfdec_player_unroot (player, resource);
- return FALSE;
- }
- movie = swfdec_player_get_movie_at_level (player, level);
- }
- if (movie == NULL) {
- movie = swfdec_player_create_movie_at_level (player, resource, level);
- } else {
- /* FIXME: is this correct? */
- movie = swfdec_resource_replace_movie (movie, resource);
- }
- SWFDEC_ACTOR (movie)->focusrect = SWFDEC_FLASH_YES;
- swfdec_player_unroot (player, resource);
- return TRUE;
-}
-
static void
swfdec_resource_stream_target_open (SwfdecStreamTarget *target, SwfdecStream *stream)
{
@@ -238,8 +210,7 @@ swfdec_resource_stream_target_open (SwfdecStreamTarget *target, SwfdecStream *st
SwfdecResource *instance = SWFDEC_RESOURCE (target);
const char *query;
- if (!swfdec_resource_create_movie (instance))
- return;
+ g_assert (instance->movie);
query = swfdec_url_get_query (swfdec_loader_get_url (loader));
if (query) {
SWFDEC_INFO ("set url query movie variables: %s", query);
@@ -427,7 +398,6 @@ swfdec_resource_dispose (GObject *object)
g_object_unref (resource->decoder);
resource->decoder = NULL;
}
- g_free (resource->target);
g_free (resource->variables);
g_hash_table_destroy (resource->exports);
g_hash_table_destroy (resource->export_names);
@@ -522,12 +492,12 @@ swfdec_resource_add_export (SwfdecResource *instance, SwfdecCharacter *character
typedef struct _SwfdecResourceLoad SwfdecResourceLoad;
struct _SwfdecResourceLoad {
SwfdecSandbox * sandbox;
- char * target;
+ char * target_string;
+ SwfdecSpriteMovie * target_movie;
char * url;
SwfdecLoaderRequest request;
SwfdecBuffer * buffer;
SwfdecMovieClipLoader * loader;
- gboolean target_is_movie;
};
static void
@@ -537,7 +507,7 @@ swfdec_resource_load_free (gpointer loadp)
swfdec_player_unroot (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (load->sandbox)->context), load);
g_free (load->url);
- g_free (load->target);
+ g_free (load->target_string);
if (load->buffer)
swfdec_buffer_unref (load->buffer);
g_slice_free (SwfdecResourceLoad, load);
@@ -551,6 +521,37 @@ swfdec_resource_load_mark (gpointer loadp, gpointer playerp)
swfdec_as_object_mark (SWFDEC_AS_OBJECT (load->sandbox));
if (load->loader)
swfdec_as_object_mark (SWFDEC_AS_OBJECT (load->loader));
+ if (load->target_movie)
+ swfdec_as_object_mark (SWFDEC_AS_OBJECT (load->target_movie));
+}
+
+static gboolean
+swfdec_resource_create_movie (SwfdecResource *resource, SwfdecResourceLoad *load)
+{
+ SwfdecPlayer *player;
+ SwfdecSpriteMovie *movie;
+
+ if (resource->movie)
+ return TRUE;
+ player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (resource)->context);
+ if (load->target_movie) {
+ movie = (SwfdecSpriteMovie *) swfdec_movie_resolve (SWFDEC_MOVIE (load->target_movie));
+ if (SWFDEC_IS_SPRITE_MOVIE (movie))
+ movie = swfdec_resource_replace_movie (movie, resource);
+ else
+ movie = NULL;
+ } else {
+ int level = swfdec_player_get_level (player, load->target_string);
+ if (level >= 0)
+ movie = swfdec_player_create_movie_at_level (player, resource, level);
+ }
+ if (movie == NULL) {
+ SWFDEC_WARNING ("target does not reference a movie, not loading %s", load->url);
+ return FALSE;
+ }
+ /* FIXME: does this belong here? */
+ SWFDEC_ACTOR (movie)->focusrect = SWFDEC_FLASH_YES;
+ return TRUE;
}
static void
@@ -565,13 +566,12 @@ swfdec_resource_do_load (SwfdecPlayer *player, gboolean allowed, gpointer loadp)
resource = g_object_new (SWFDEC_TYPE_RESOURCE, NULL);
swfdec_as_object_add (SWFDEC_AS_OBJECT (resource), SWFDEC_AS_CONTEXT (player), sizeof (SwfdecResource));
resource->version = 8;
- resource->target = g_strdup (load->target);
if (load->loader) {
resource->clip_loader = load->loader;
resource->clip_loader_sandbox = load->sandbox;
}
+ resource->target = SWFDEC_MOVIE (load->target_movie);
resource->sandbox = load->sandbox;
-
if (!allowed) {
SWFDEC_WARNING ("SECURITY: no access to %s from %s",
load->url, swfdec_url_get_url (load->sandbox->url));
@@ -580,8 +580,10 @@ swfdec_resource_do_load (SwfdecPlayer *player, gboolean allowed, gpointer loadp)
return;
}
- swfdec_player_root (player, resource, (GFunc) swfdec_as_object_mark);
- loader = swfdec_player_load (player, load-> url, load->request, load->buffer);
+ /* FIXME: load nonetheless, even if there's no movie? */
+ if (!swfdec_resource_create_movie (resource, load))
+ return;
+ loader = swfdec_player_load (player, load->url, load->request, load->buffer);
swfdec_resource_set_loader (resource, loader);
g_object_unref (loader);
}
@@ -597,9 +599,7 @@ swfdec_resource_load_request (gpointer loadp, gpointer playerp)
if (load->url[0] == '\0') {
SwfdecSpriteMovie *movie;
- movie = (SwfdecSpriteMovie *) swfdec_action_lookup_object (
- SWFDEC_AS_CONTEXT (player), player->priv->roots->data,
- load->target, load->target + strlen (load->target));
+ movie = load->target_movie ? (SwfdecSpriteMovie *) swfdec_movie_resolve (SWFDEC_MOVIE (load->target_movie)) : NULL;
if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
SWFDEC_DEBUG ("no movie, not unloading");
return;
@@ -611,13 +611,21 @@ swfdec_resource_load_request (gpointer loadp, gpointer playerp)
/* fscommand? */
if (g_ascii_strncasecmp (load->url, "FSCommand:", 10) == 0) {
char *command = load->url + 10;
- g_signal_emit_by_name (player, "fscommand", command, load->target);
+ if (load->target_movie) {
+ char *target = swfdec_movie_get_path (SWFDEC_MOVIE (load->target_movie), TRUE);
+ SWFDEC_FIXME ("Adobe 9.0.124.0 and later don't emit fscommands here. "
+ "We just do for compatibility reasons with the testsuite.");
+ g_signal_emit_by_name (player, "fscommand", command, target);
+ g_free (target);
+ } else {
+ g_signal_emit_by_name (player, "fscommand", command, load->target_string);
+ }
return;
}
/* LAUNCH command (aka getURL) */
- if (!load->target_is_movie && swfdec_player_get_level (player, load->target) < 0) {
- swfdec_player_launch (player, load->request, load->url,load->target, load->buffer);
+ if (load->target_string && swfdec_player_get_level (player, load->target_string) < 0) {
+ swfdec_player_launch (player, load->request, load->url,load->target_string, load->buffer);
return;
}
@@ -655,46 +663,75 @@ swfdec_resource_load_request (gpointer loadp, gpointer playerp)
/* NB: must be called from a script */
/* FIXME: 7 arguments?! */
-void
-swfdec_resource_load (SwfdecPlayer *player, const char *target, const char *url,
- SwfdecLoaderRequest request, SwfdecBuffer *buffer, SwfdecMovieClipLoader *loader,
- gboolean target_is_movie)
+static void
+swfdec_resource_load_internal (SwfdecPlayer *player, SwfdecSpriteMovie *target_movie,
+ const char *target_string, const char *url, SwfdecLoaderRequest request,
+ SwfdecBuffer *buffer, SwfdecMovieClipLoader *loader)
{
- SwfdecSpriteMovie *movie;
SwfdecResourceLoad *load;
- g_return_if_fail (SWFDEC_IS_PLAYER (player));
- g_return_if_fail (target != NULL);
- g_return_if_fail (url != NULL);
- g_return_if_fail (loader == NULL || SWFDEC_IS_MOVIE_CLIP_LOADER (loader));
-
g_assert (SWFDEC_AS_CONTEXT (player)->frame != NULL);
load = g_slice_new (SwfdecResourceLoad);
- if (target_is_movie) {
- movie = (SwfdecSpriteMovie *) swfdec_player_get_movie_from_string (player, target);
- if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
- load->target = swfdec_movie_get_path (SWFDEC_MOVIE (movie), TRUE);
- } else if (swfdec_player_get_level (player, target) >= 0) {
- load->target = g_strdup (target);
- } else {
- SWFDEC_WARNING ("%s does not reference a movie, not loading %s", target, url);
- return;
- }
- } else {
- load->target = g_strdup (target);
- }
load->sandbox = SWFDEC_SANDBOX (SWFDEC_AS_CONTEXT (player)->global);
load->url = g_strdup (url);
+ load->target_movie = target_movie;
+ load->target_string = g_strdup (target_string);
load->request = request;
load->buffer = buffer;
load->loader = loader;
- load->target_is_movie = target_is_movie;
swfdec_player_root (player, load, swfdec_resource_load_mark);
swfdec_player_request_resource (player, swfdec_resource_load_request, load, swfdec_resource_load_free);
}
+void
+swfdec_resource_load_movie (SwfdecPlayer *player, const SwfdecAsValue *target,
+ const char *url, SwfdecLoaderRequest request, SwfdecBuffer *buffer,
+ SwfdecMovieClipLoader *loader)
+{
+ SwfdecMovie *movie;
+ const char *s;
+
+ g_return_if_fail (SWFDEC_IS_PLAYER (player));
+ g_return_if_fail (target != NULL);
+ g_return_if_fail (url != NULL);
+ g_return_if_fail (loader == NULL || SWFDEC_IS_MOVIE_CLIP_LOADER (loader));
+
+ if (SWFDEC_AS_VALUE_IS_OBJECT (target)) {
+ SwfdecAsObject *object = SWFDEC_AS_VALUE_GET_OBJECT (target);
+ if (SWFDEC_IS_SPRITE_MOVIE (object)) {
+ swfdec_resource_load_internal (player, SWFDEC_SPRITE_MOVIE (object),
+ NULL, url, request, buffer, loader);
+ return;
+ }
+ }
+
+ s = swfdec_as_value_to_string (SWFDEC_AS_CONTEXT (player), target);
+ movie = swfdec_player_get_movie_from_string (player, s);
+ if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
+ swfdec_resource_load_internal (player, SWFDEC_SPRITE_MOVIE (movie),
+ NULL, url, request, buffer, loader);
+ return;
+ }
+ if (swfdec_player_get_level (player, s) < 0) {
+ SWFDEC_WARNING ("%s does not reference a movie, not loading %s", s, url);
+ return;
+ }
+ swfdec_resource_load_internal (player, NULL, s, url, request, buffer, NULL);
+}
+
+void
+swfdec_resource_load (SwfdecPlayer *player, const char *target,
+ const char *url, SwfdecLoaderRequest request, SwfdecBuffer *buffer)
+{
+ g_return_if_fail (SWFDEC_IS_PLAYER (player));
+ g_return_if_fail (target != NULL);
+ g_return_if_fail (url != NULL);
+
+ swfdec_resource_load_internal (player, NULL, target, url, request, buffer, NULL);
+}
+
gboolean
swfdec_resource_emit_on_load_init (SwfdecResource *resource)
{
diff --git a/swfdec/swfdec_resource.h b/swfdec/swfdec_resource.h
index 3496789..d1c977f 100644
--- a/swfdec/swfdec_resource.h
+++ b/swfdec/swfdec_resource.h
@@ -60,7 +60,7 @@ struct _SwfdecResource
/* only used while loading */
SwfdecResourceState state; /* state we're in (for determining callbacks */
- char * target; /* target path we use for signalling */
+ SwfdecMovie * target; /* target path we use for signalling */
SwfdecMovieClipLoader *clip_loader; /* loader that gets notified about load events */
SwfdecSandbox * clip_loader_sandbox; /* sandbox used for events on the clip loader */
};
@@ -85,13 +85,17 @@ gpointer swfdec_resource_get_export (SwfdecResource * root,
const char * swfdec_resource_get_export_name (SwfdecResource * root,
SwfdecCharacter * character);
+void swfdec_resource_load_movie (SwfdecPlayer * player,
+ const SwfdecAsValue * target,
+ const char * url,
+ SwfdecLoaderRequest request,
+ SwfdecBuffer * buffer,
+ SwfdecMovieClipLoader *loader);
void swfdec_resource_load (SwfdecPlayer * player,
const char * target,
const char * url,
SwfdecLoaderRequest request,
- SwfdecBuffer * buffer,
- SwfdecMovieClipLoader *loader,
- gboolean target_is_movie);
+ SwfdecBuffer * buffer);
G_END_DECLS
commit 481af6efca33b51981d567a89666a9391aca3868
Author: Benjamin Otte <otte at gnome.org>
Date: Thu May 29 11:08:30 2008 +0200
only render the frames that are available
This is in a pretty ugly state, as I haven't yet figured out the API semantics
I want SwfdecAudio to provide in the future yet, in particular the behavior of
"no more data available for rendering right now"
diff --git a/swfdec-gtk/swfdec_playback_alsa.c b/swfdec-gtk/swfdec_playback_alsa.c
index 5ecff13..be9f4f9 100644
--- a/swfdec-gtk/swfdec_playback_alsa.c
+++ b/swfdec-gtk/swfdec_playback_alsa.c
@@ -74,30 +74,45 @@ struct _Stream {
/*** STREAMS ***/
+static void
+swfdec_playback_stream_remove_handlers (Stream *stream)
+{
+ guint i;
+
+ for (i = 0; i < stream->n_sources; i++) {
+ if (stream->sources[i]) {
+ g_source_destroy (stream->sources[i]);
+ g_source_unref (stream->sources[i]);
+ stream->sources[i] = NULL;
+ }
+ }
+}
+
static snd_pcm_uframes_t
write_player (Stream *stream, const snd_pcm_channel_area_t *dst,
snd_pcm_uframes_t offset, snd_pcm_uframes_t avail)
{
+ snd_pcm_uframes_t rendered;
/* FIXME: do a long path if this doesn't hold */
g_assert (dst[1].first - dst[0].first == 16);
g_assert (dst[0].addr == dst[1].addr);
g_assert (dst[0].step == dst[1].step);
g_assert (dst[0].step == 32);
- swfdec_audio_render (stream->audio, (gint16 *) ((guint8 *) dst[0].addr + offset * dst[0].step / 8),
+ rendered = swfdec_audio_render (stream->audio, (gint16 *) ((guint8 *) dst[0].addr + offset * dst[0].step / 8),
stream->offset, avail);
//g_print ("rendering %u %u\n", stream->offset, (guint) avail);
- return avail;
+ return rendered;
}
static gboolean
try_write_mmap (Stream *stream)
{
snd_pcm_sframes_t avail_result;
- snd_pcm_uframes_t offset, avail;
+ snd_pcm_uframes_t offset, avail, rendered;
const snd_pcm_channel_area_t *dst;
- while (TRUE) {
+ do {
avail_result = snd_pcm_avail_update (stream->pcm);
ALSA_ERROR (avail_result, "snd_pcm_avail_update failed", FALSE);
if (avail_result == 0)
@@ -107,14 +122,15 @@ try_write_mmap (Stream *stream)
"snd_pcm_mmap_begin failed", FALSE);
//g_print (" avail = %u\n", (guint) avail);
- avail = write_player (stream, dst, offset, avail);
- if (snd_pcm_mmap_commit (stream->pcm, offset, avail) < 0) {
+ rendered = write_player (stream, dst, offset, avail);
+ if (snd_pcm_mmap_commit (stream->pcm, offset, rendered) < 0) {
g_printerr ("snd_pcm_mmap_commit failed\n");
return FALSE;
}
- stream->offset += avail;
+ stream->offset += rendered;
//g_print ("offset: %u (+%u)\n", stream->offset, (guint) avail);
- }
+ } while (rendered == avail);
+ swfdec_playback_stream_remove_handlers (stream);
return TRUE;
}
@@ -122,41 +138,33 @@ static gboolean
try_write_so_pa_gets_it (Stream *stream)
{
#define STEP 1024
- snd_pcm_sframes_t avail, step;
+ snd_pcm_sframes_t avail, step, written;
+ gboolean finish = FALSE;
+
avail = snd_pcm_avail_update (stream->pcm);
ALSA_ERROR (avail, "snd_pcm_avail_update failed", FALSE);
- while (avail > 0) {
+ while (avail > 0 && !finish) {
gint16 data[2 * STEP];
step = MIN (avail, STEP);
- swfdec_audio_render (stream->audio, data, stream->offset, step);
- step = snd_pcm_writei (stream->pcm, data, step);
+ written = swfdec_audio_render (stream->audio, data, stream->offset, step);
+ finish = written < step;
+ step = snd_pcm_writei (stream->pcm, data, written);
+ finish &= step == written;
ALSA_ERROR (step, "snd_pcm_writei failed", FALSE);
avail -= step;
stream->offset += step;
}
+ if (finish)
+ swfdec_playback_stream_remove_handlers (stream);
return TRUE;
#undef STEP
}
#define try_write(stream) ((stream)->write (stream))
-static void
-swfdec_playback_stream_remove_handlers (Stream *stream)
-{
- guint i;
-
- for (i = 0; i < stream->n_sources; i++) {
- if (stream->sources[i]) {
- g_source_destroy (stream->sources[i]);
- g_source_unref (stream->sources[i]);
- stream->sources[i] = NULL;
- }
- }
-}
-
static void swfdec_playback_stream_start (Stream *stream);
static gboolean
handle_stream (GIOChannel *source, GIOCondition cond, gpointer data)
commit f219286ed43a0f32dc37ace59a49818dcea68de5
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 28 16:29:46 2008 +0200
don't add the samples twice (oops)
diff --git a/swfdec/swfdec_audio_event.c b/swfdec/swfdec_audio_event.c
index 528a848..10114e4 100644
--- a/swfdec/swfdec_audio_event.c
+++ b/swfdec/swfdec_audio_event.c
@@ -107,7 +107,6 @@ swfdec_audio_event_render (SwfdecAudio *audio, gint16* dest, guint start,
rendered += samples;
dest_end += samples * 2;
offset = 0;
- rendered += samples;
}
if (event->n_envelopes == 0)
commit 774bd64f867072d93b3eb0e2b2e9f390b65b8c66
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 28 16:23:14 2008 +0200
make tools compile
diff --git a/tools/dump.c b/tools/dump.c
index 0c83728..eb56c4b 100644
--- a/tools/dump.c
+++ b/tools/dump.c
@@ -83,24 +83,6 @@ dump_sprite (SwfdecSwfDecoder *dec, SwfdecSprite *s)
} else {
guint i, j, tag;
SwfdecBuffer *buffer;
- SwfdecSound *sound = NULL;
-
- for (i = 0; i < s->n_frames; i++) {
- SwfdecSpriteFrame *frame = &s->frames[i];
- if (frame->sound_head != sound &&
- frame->sound_block != NULL) {
- sound = frame->sound_head;
- for (j = i; j < s->n_frames; j++) {
- SwfdecSpriteFrame *cur = &s->frames[i];
- if (cur->sound_head != sound)
- break;
- }
- if (sound)
- g_print (" %4u -%4u sound: %s %s\n", i, j,
- get_audio_format_name (sound->codec),
- swfdec_audio_format_to_string (sound->format));
- }
- }
j = 0;
for (i = 0; ; i++) {
@@ -160,6 +142,13 @@ dump_sprite (SwfdecSwfDecoder *dec, SwfdecSprite *s)
case SWFDEC_TAG_SETBACKGROUNDCOLOR:
g_print (" %4u background color\n", j);
break;
+ case SWFDEC_TAG_SOUNDSTREAMHEAD:
+ /* FIXME */
+ g_print (" %4u sound stream\n", j);
+ break;
+ case SWFDEC_TAG_SOUNDSTREAMHEAD2:
+ case SWFDEC_TAG_SOUNDSTREAMBLOCK:
+ break;
default:
g_assert_not_reached ();
}
diff --git a/tools/swfdec-extract.c b/tools/swfdec-extract.c
index 3af5cf0..f8ec144 100644
--- a/tools/swfdec-extract.c
+++ b/tools/swfdec-extract.c
@@ -100,31 +100,20 @@ export_sound (SwfdecSound *sound, const char *filename)
static gboolean
export_sprite_sound (SwfdecSprite *sprite, const char *filename)
{
+ g_printerr ("FIXME: Someone implement sound export from sprites plz\n");
+ return FALSE;
+#if 0
GError *error = NULL;
guint i, depth;
SwfdecAudio *audio;
SwfdecBufferQueue *queue;
SwfdecBuffer *buffer, *wav;
- for (i = 0; i < sprite->n_frames; i++) {
- if (sprite->frames[i].sound_head)
- break;
- }
- if (i >= sprite->n_frames) {
- g_printerr ("No sound in sprite %u\n", SWFDEC_CHARACTER (sprite)->id);
- return FALSE;
- }
audio = swfdec_audio_stream_new (NULL, sprite, i);
i = 4096;
queue = swfdec_buffer_queue_new ();
while (i > 0) {
buffer = swfdec_buffer_new0 (i * 4);
-#if 0
- if (i > 1234) {
- swfdec_audio_render (audio, (gint16 *) buffer->data, 0, 1234);
- swfdec_audio_render (audio, (gint16 *) buffer->data + 2468, 1234, i - 1234);
- } else
-#endif
{
swfdec_audio_render (audio, (gint16 *) (void *) buffer->data, 0, i);
}
@@ -151,6 +140,7 @@ export_sprite_sound (SwfdecSprite *sprite, const char *filename)
}
swfdec_buffer_unref (wav);
return TRUE;
+#endif
}
static cairo_surface_t *
commit dd1d7c332eedb396847976a4bfa238d1a0e77a44
Author: Benjamin Otte <otte at gnome.org>
Date: Wed May 28 16:05:05 2008 +0200
rework audio stream handling
changes:
- SwfdecAudioSoundStream is a new base class for sound streams. To be used for
FLV and Sound.loadSound()
- SwfdecAudioSwfSoundStream is what used to be SwfdecAudioSoundStream.
- SoundStream(Head,Head2,Block) tags are now enqueued
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 33edc71..b887678 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -40,6 +40,7 @@ libswfdec_source_files = \
swfdec_audio_event.c \
swfdec_audio_flv.c \
swfdec_audio_stream.c \
+ swfdec_audio_swf_stream.c \
swfdec_bevel_filter.c \
swfdec_bitmap_data.c \
swfdec_bitmap_filter.c \
@@ -234,6 +235,7 @@ noinst_HEADERS = \
swfdec_audio_event.h \
swfdec_audio_flv.h \
swfdec_audio_stream.h \
+ swfdec_audio_swf_stream.h \
swfdec_bits.h \
swfdec_bots.h \
swfdec_button.h \
diff --git a/swfdec/swfdec_audio_decoder.c b/swfdec/swfdec_audio_decoder.c
index 90d2b36..6f7f0e7 100644
--- a/swfdec/swfdec_audio_decoder.c
+++ b/swfdec/swfdec_audio_decoder.c
@@ -217,3 +217,25 @@ swfdec_audio_decoder_errorv (SwfdecAudioDecoder *decoder, const char *error, va_
decoder->error = TRUE;
}
+/**
+ * swfdec_audio_decoder_uses_format:
+ * @decoder: the decoder to check
+ * @codec: the codec the decoder should use
+ * @format: the format the decoder should use
+ *
+ * This is a little helper function that checks if the decoder uses the right
+ * format.
+ *
+ * Returns: %TRUE if the @decoder uses the given @codec and @format, %FALSE
+ * otherwise.
+ **/
+gboolean
+swfdec_audio_decoder_uses_format (SwfdecAudioDecoder *decoder, guint codec,
+ SwfdecAudioFormat format)
+{
+ g_return_val_if_fail (SWFDEC_IS_AUDIO_DECODER (decoder), FALSE);
+ g_return_val_if_fail (SWFDEC_IS_AUDIO_FORMAT (format), FALSE);
+
+ return decoder->codec == codec && decoder->format == format;
+}
+
diff --git a/swfdec/swfdec_audio_decoder.h b/swfdec/swfdec_audio_decoder.h
index 6d58303..3f4363a 100644
--- a/swfdec/swfdec_audio_decoder.h
+++ b/swfdec/swfdec_audio_decoder.h
@@ -74,6 +74,9 @@ SwfdecAudioDecoder * swfdec_audio_decoder_new (guint codec,
void swfdec_audio_decoder_push (SwfdecAudioDecoder * decoder,
SwfdecBuffer * buffer);
SwfdecBuffer * swfdec_audio_decoder_pull (SwfdecAudioDecoder * decoder);
+gboolean swfdec_audio_decoder_uses_format(SwfdecAudioDecoder * decoder,
+ guint codec,
+ SwfdecAudioFormat format);
/* for subclasses */
void swfdec_audio_decoder_error (SwfdecAudioDecoder * decoder,
diff --git a/swfdec/swfdec_audio_stream.c b/swfdec/swfdec_audio_stream.c
index 3c73ad1..b5f47c1 100644
--- a/swfdec/swfdec_audio_stream.c
+++ b/swfdec/swfdec_audio_stream.c
@@ -41,40 +41,38 @@ swfdec_audio_stream_dispose (GObject *object)
g_object_unref (stream->decoder);
stream->decoder = NULL;
}
- g_queue_foreach (stream->playback_queue, (GFunc) swfdec_buffer_unref, NULL);
- g_queue_free (stream->playback_queue);
+ g_queue_foreach (stream->queue, (GFunc) swfdec_buffer_unref, NULL);
+ g_queue_free (stream->queue);
G_OBJECT_CLASS (swfdec_audio_stream_parent_class)->dispose (object);
}
-static SwfdecBuffer *
-swfdec_audio_stream_decode_one (SwfdecAudioStream *stream)
+/* returns: number of samples available */
+static void
+swfdec_audio_stream_require (SwfdecAudioStream *stream, guint n_samples)
{
- SwfdecSpriteFrame *frame;
+ SwfdecAudioStreamClass *klass = SWFDEC_AUDIO_STREAM_GET_CLASS (stream);
SwfdecBuffer *buffer;
- g_assert (!stream->done);
- if (stream->decoder == NULL)
- return NULL;
-
- while (!(buffer = swfdec_audio_decoder_pull (stream->decoder)) &&
- !stream->done) {
- if (stream->current_frame >= stream->sprite->n_frames)
- goto end;
- frame = &stream->sprite->frames[stream->current_frame];
- stream->current_frame++;
- if (frame->sound_head != stream->sound)
- goto end;
- if (frame->sound_samples == 0)
+ /* subclasses are responsible for having set a proper decoder */
+ g_assert (SWFDEC_IS_AUDIO_DECODER (stream->decoder));
+
+ while (stream->queue_size < n_samples && !stream->done) {
+ /* if the decoder still has data */
+ buffer = swfdec_audio_decoder_pull (stream->decoder);
+ if (buffer) {
+ g_assert (buffer->length %4 == 0);
+ g_queue_push_tail (stream->queue, buffer);
+ stream->queue_size += buffer->length / 4;
continue;
- if (frame->sound_block)
- swfdec_audio_decoder_push (stream->decoder, frame->sound_block);
- continue;
-end:
- swfdec_audio_decoder_push (stream->decoder, NULL);
- stream->done = TRUE;
+ }
+ /* otherwise get a new buffer from the decoder */
+ buffer = klass->pull (stream);
+ if (buffer == NULL)
+ break;
+ swfdec_audio_decoder_push (stream->decoder, buffer);
+ swfdec_buffer_unref (buffer);
}
- return buffer;
}
static guint
@@ -83,42 +81,36 @@ swfdec_audio_stream_render (SwfdecAudio *audio, gint16* dest,
{
SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (audio);
GList *walk;
- guint samples, rendered;
+ guint samples, rendered, skip;
SwfdecBuffer *buffer;
g_assert (start < G_MAXINT);
- start += stream->playback_skip;
SWFDEC_LOG ("stream %p rendering offset %u, samples %u", stream, start, n_samples);
- walk = g_queue_peek_head_link (stream->playback_queue);
- for (rendered = 0; rendered < n_samples;) {
- if (walk) {
- buffer = walk->data;
- walk = walk->next;
- } else {
- if (stream->done)
- break;
- 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,
- swfdec_audio_format_new (44100, 2, TRUE));
- if (start) {
- if (samples <= start) {
- start -= samples;
- continue;
- }
- samples -= start;
- SWFDEC_LOG ("rendering %u samples, skipping %u",
- samples, start);
+ swfdec_audio_stream_require (stream, start + n_samples);
+ if (stream->queue_size <= start)
+ return 0;
+ n_samples = MIN (stream->queue_size, n_samples + start);
+
+ rendered = 0;
+ for (walk = g_queue_peek_head_link (stream->queue);
+ rendered < n_samples; walk = walk->next) {
+ /* must hold, we check above that enough data is available */
+ g_assert (walk);
+ buffer = walk->data;
+ samples = buffer->length / 4;
+ if (rendered < start) {
+ skip = MIN (samples, start - rendered);
+ samples -= skip;
+ samples = MIN (n_samples - start, samples);
} else {
- SWFDEC_LOG ("rendering %u samples", samples);
+ skip = 0;
+ samples = MIN (n_samples - rendered, samples);
}
- samples = MIN (samples, n_samples - rendered);
- swfdec_sound_buffer_render (dest, buffer, start, samples);
- start = 0;
- rendered += samples;
+ samples = MIN (n_samples - MAX (start, rendered), samples);
+ if (samples)
+ swfdec_sound_buffer_render (dest, buffer, skip, samples);
+
+ rendered += skip + samples;
dest += 2 * samples;
}
@@ -130,33 +122,28 @@ swfdec_audio_stream_iterate (SwfdecAudio *audio, guint remove)
{
SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (audio);
SwfdecBuffer *buffer;
-
- stream->playback_skip += remove;
- buffer = g_queue_peek_head (stream->playback_queue);
- while (buffer && stream->playback_skip >=
- swfdec_sound_buffer_get_n_samples (buffer, swfdec_audio_format_new (44100, 2, TRUE))
- + swfdec_audio_format_get_granularity (swfdec_audio_format_new (44100, 2, TRUE))) {
- buffer = g_queue_pop_head (stream->playback_queue);
- SWFDEC_LOG ("removing buffer with %u samples",
- swfdec_sound_buffer_get_n_samples (buffer,
- swfdec_audio_format_new (44100, 2, TRUE)));
- stream->playback_skip -= swfdec_sound_buffer_get_n_samples (buffer,
- swfdec_audio_format_new (44100, 2, TRUE));
- swfdec_buffer_unref (buffer);
- buffer = g_queue_peek_head (stream->playback_queue);
+ guint samples, cur_samples;
+
+ swfdec_audio_stream_require (stream, remove);
+ samples = MIN (remove, stream->queue_size);
+
+ while (samples > 0) {
+ buffer = g_queue_pop_head (stream->queue);
+ cur_samples = buffer->length / 4;
+ if (samples < cur_samples) {
+ SwfdecBuffer *sub = swfdec_buffer_new_subbuffer (buffer,
+ samples * 4, buffer->length - samples * 4);
+ g_queue_push_head (stream->queue, sub);
+ cur_samples = samples;
+ }
+ stream->queue_size -= cur_samples;
+ samples -= cur_samples;
}
if (!stream->done) {
return G_MAXUINT;
} else {
- GList *walk;
- guint ret = 0;
- SwfdecAudioFormat format = swfdec_audio_format_new (44100, 2, TRUE);
-
- for (walk = g_queue_peek_head_link (stream->playback_queue); walk; walk = walk->next) {
- ret += swfdec_sound_buffer_get_n_samples (walk->data, format);
- }
- return ret - stream->playback_skip;
+ return stream->queue_size;
}
}
@@ -175,29 +162,31 @@ swfdec_audio_stream_class_init (SwfdecAudioStreamClass *klass)
static void
swfdec_audio_stream_init (SwfdecAudioStream *stream)
{
- stream->playback_queue = g_queue_new ();
+ stream->queue = g_queue_new ();
}
-SwfdecAudio *
-swfdec_audio_stream_new (SwfdecPlayer *player, SwfdecSprite *sprite, guint start_frame)
+void
+swfdec_audio_stream_use_decoder (SwfdecAudioStream *stream,
+ guint codec, SwfdecAudioFormat format)
{
- SwfdecAudioStream *stream;
- SwfdecSpriteFrame *frame;
-
- stream = g_object_new (SWFDEC_TYPE_AUDIO_STREAM, NULL);
-
- SWFDEC_DEBUG ("new audio stream for sprite %d, starting at %u",
- SWFDEC_CHARACTER (sprite)->id, start_frame);
- stream->sprite = sprite;
- frame = &sprite->frames[start_frame];
- g_assert (frame->sound_head);
- stream->sound = frame->sound_head;
- stream->playback_skip = frame->sound_skip;
- stream->current_frame = start_frame;
- stream->decoder = swfdec_audio_decoder_new (stream->sound->codec,
- stream->sound->format);
- swfdec_audio_add (SWFDEC_AUDIO (stream), player);
-
- return SWFDEC_AUDIO (stream);
+ g_return_if_fail (SWFDEC_IS_AUDIO_STREAM (stream));
+ g_return_if_fail (SWFDEC_IS_AUDIO_FORMAT (format));
+
+ if (stream->decoder) {
+ if (swfdec_audio_decoder_uses_format (stream->decoder, codec, format))
+ return;
+ /* FIXME: send NULL buffer */
+ g_object_unref (stream->decoder);
+ }
+ stream->decoder = swfdec_audio_decoder_new (codec, format);
+}
+
+void
+swfdec_audio_stream_done (SwfdecAudioStream *stream)
+{
+ g_return_if_fail (SWFDEC_IS_AUDIO_STREAM (stream));
+ g_return_if_fail (stream->done);
+
+ stream->done = TRUE;
}
diff --git a/swfdec/swfdec_audio_stream.h b/swfdec/swfdec_audio_stream.h
index 7959653..96ea53f 100644
--- a/swfdec/swfdec_audio_stream.h
+++ b/swfdec/swfdec_audio_stream.h
@@ -1,7 +1,7 @@
/* Swfdec
* Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
* 2005-2006 Eric Anholt <eric at anholt.net>
- * 2006 Benjamin Otte <otte at gnome.org>
+ * 2006-2008 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
@@ -41,25 +41,27 @@ struct _SwfdecAudioStream
{
SwfdecAudio audio;
- SwfdecSprite * sprite; /* sprite we're playing back */
- SwfdecSound * sound; /* sound we're playing */
- 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 */
- gboolean done; /* TRUE when no new data will be made available */
+ SwfdecAudioDecoder * decoder; /* decoder in use */
+ GQueue * queue; /* all the samples we've decoded so far */
+ guint queue_size; /* size of queue in samples */
+ gboolean done; /* no more data will arrive */
};
struct _SwfdecAudioStreamClass
{
SwfdecAudioClass audio_class;
+
+ /* get another buffer if available */
+ SwfdecBuffer * (* pull) (SwfdecAudioStream * stream);
};
GType swfdec_audio_stream_get_type (void);
-SwfdecAudio * swfdec_audio_stream_new (SwfdecPlayer * player,
- SwfdecSprite * sprite,
- guint start_frame);
+/* to be called from pull callback */
+void swfdec_audio_stream_use_decoder (SwfdecAudioStream * stream,
+ guint codec,
+ SwfdecAudioFormat format);
+void swfdec_audio_stream_done (SwfdecAudioStream * stream);
G_END_DECLS
#endif
diff --git a/swfdec/swfdec_audio_swf_stream.c b/swfdec/swfdec_audio_swf_stream.c
new file mode 100644
index 0000000..eec2e5c
--- /dev/null
+++ b/swfdec/swfdec_audio_swf_stream.c
@@ -0,0 +1,216 @@
+/* Swfdec
+ * Copyright (C) 2008 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 <string.h>
+#include "swfdec_audio_swf_stream.h"
+#include "swfdec_debug.h"
+#include "swfdec_sprite.h"
+#include "swfdec_tag.h"
+
+
+G_DEFINE_TYPE (SwfdecAudioSwfStream, swfdec_audio_swf_stream, SWFDEC_TYPE_AUDIO_STREAM)
+
+static void
+swfdec_audio_swf_stream_dispose (GObject *object)
+{
+ SwfdecAudioSwfStream *stream = SWFDEC_AUDIO_SWF_STREAM (object);
+
+ if (stream->sprite != NULL) {
+ g_object_unref (stream->sprite);
+ stream->sprite = NULL;
+ }
+
+ G_OBJECT_CLASS (swfdec_audio_swf_stream_parent_class)->dispose (object);
+}
+
+static void
+swfdec_audio_swf_stream_head (SwfdecAudioSwfStream *stream, SwfdecBuffer *buffer)
+{
+ SwfdecBits bits;
+ SwfdecAudioFormat playback_format, format;
+ guint playback_codec, codec;
+ int n_samples;
+ guint latency = 0;
+
+ swfdec_bits_init (&bits, buffer);
+
+ /* we don't care about playback suggestions */
+ playback_codec = swfdec_bits_getbits (&bits, 4);
+ playback_format = swfdec_audio_format_parse (&bits);
+ SWFDEC_LOG (" suggested playback format: %s", swfdec_audio_format_to_string (playback_format));
+
+ codec = swfdec_bits_getbits (&bits, 4);
+ format = swfdec_audio_format_parse (&bits);
+ n_samples = swfdec_bits_get_u16 (&bits);
+ SWFDEC_LOG (" codec: %u", codec);
+ SWFDEC_LOG (" format: %s", swfdec_audio_format_to_string (format));
+ SWFDEC_LOG (" samples: %u", n_samples);
+
+ switch (codec) {
+ case SWFDEC_AUDIO_CODEC_UNDEFINED:
+ if (swfdec_audio_format_is_16bit (format)) {
+ SWFDEC_WARNING ("undefined endianness for s16 sound");
+ /* just assume LE and hope it works (FIXME: want a switch for this?) */
+ codec = SWFDEC_AUDIO_CODEC_UNCOMPRESSED;
+ }
+ break;
+ case SWFDEC_AUDIO_CODEC_MP3:
+ /* latency seek */
+ latency = swfdec_bits_get_u16 (&bits);
+ break;
+ case SWFDEC_AUDIO_CODEC_ADPCM:
+ case SWFDEC_AUDIO_CODEC_UNCOMPRESSED:
+ case SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ:
+ case SWFDEC_AUDIO_CODEC_NELLYMOSER:
+ break;
+ default:
+ SWFDEC_WARNING ("unknown codec %u", codec);
+ break;
+ }
+
+ swfdec_audio_stream_use_decoder (SWFDEC_AUDIO_STREAM (stream), codec, format);
+}
+
+static SwfdecBuffer *
+swfdec_audio_swf_stream_block (SwfdecAudioSwfStream *stream, SwfdecBuffer *buffer)
+{
+ SwfdecBits bits;
+ guint n_samples;
+ int skip;
+
+ swfdec_bits_init (&bits, buffer);
+
+ /* FIXME: we want accessor functions for this */
+ if (SWFDEC_AUDIO_STREAM (stream)->decoder->codec == SWFDEC_AUDIO_CODEC_MP3) {
+ n_samples = swfdec_bits_get_u16 (&bits);
+ skip = swfdec_bits_get_s16 (&bits);
+ }
+ buffer = swfdec_bits_get_buffer (&bits, -1);
+ /* use this to write out the stream data to stdout - nice way to get an mp3 file :) */
+ //write (1, (void *) buffer->data, buffer->length);
+
+ return buffer;
+}
+
+static SwfdecBuffer *
+swfdec_audio_swf_stream_pull (SwfdecAudioStream *audio)
+{
+ SwfdecAudioSwfStream *stream = SWFDEC_AUDIO_SWF_STREAM (audio);
+ SwfdecBuffer *buffer;
+ guint tag;
+
+ do {
+ if (!swfdec_sprite_get_action (stream->sprite, stream->id, &tag, &buffer)) {
+ if (swfdec_sprite_is_loaded (stream->sprite))
+ swfdec_audio_stream_done (audio);
+ buffer = NULL;
+ break;
+ }
+ stream->id++;
+ switch (tag) {
+ case SWFDEC_TAG_SOUNDSTREAMHEAD:
+ case SWFDEC_TAG_SOUNDSTREAMHEAD2:
+ swfdec_audio_swf_stream_head (stream, buffer);
+ break;
+ case SWFDEC_TAG_SOUNDSTREAMBLOCK:
+ buffer = swfdec_audio_swf_stream_block (stream, buffer);
+ break;
+ default:
+ break;
+ }
+ } while (tag != SWFDEC_TAG_SOUNDSTREAMBLOCK);
+
+ return buffer;
+}
+
+static void
+swfdec_audio_swf_stream_class_init (SwfdecAudioSwfStreamClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SwfdecAudioStreamClass *stream_class = SWFDEC_AUDIO_STREAM_CLASS (klass);
+
+ object_class->dispose = swfdec_audio_swf_stream_dispose;
+
+ stream_class->pull = swfdec_audio_swf_stream_pull;
+}
+
+static void
+swfdec_audio_swf_stream_init (SwfdecAudioSwfStream *stream)
+{
+}
+
+static void
+check (SwfdecAudio *audio)
+{
+ guint length = 20000;
+ gint16 *data = g_new (gint16, 2 * length);
+ gint16 *compare = g_new (gint16, 2 * length);
+ guint i;
+
+ swfdec_audio_render (audio, compare, 0, length);
+ for (i = 1; i < length; i++) {
+ swfdec_audio_render (audio, data, i, length - i);
+ g_assert (memcmp (data, compare + 2 * i, (length - i) * 4) == 0);
+ }
+
+ g_free (data);
+ g_free (compare);
+}
+
+SwfdecAudio *
+swfdec_audio_swf_stream_new (SwfdecPlayer *player, SwfdecSprite *sprite,
+ guint id)
+{
+ SwfdecAudioSwfStream *stream;
+ guint i, tag;
+ SwfdecBuffer *buffer;
+
+ g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+ g_return_val_if_fail (SWFDEC_IS_SPRITE (sprite), NULL);
+
+ stream = g_object_new (SWFDEC_TYPE_AUDIO_SWF_STREAM, NULL);
+ stream->sprite = g_object_ref (sprite);
+ stream->id = id;
+
+ i = id;
+ do {
+ i--;
+ if (!swfdec_sprite_get_action (sprite, i, &tag, &buffer)) {
+ g_assert_not_reached ();
+ }
+ if (tag == SWFDEC_TAG_SOUNDSTREAMHEAD ||
+ tag == SWFDEC_TAG_SOUNDSTREAMHEAD2) {
+ swfdec_audio_swf_stream_head (stream, buffer);
+ goto found;
+ }
+ } while (i > 0);
+ SWFDEC_ERROR ("No SoundStreamHead tag found in sprite %u",
+ SWFDEC_CHARACTER (sprite)->id);
+ swfdec_audio_stream_done (SWFDEC_AUDIO_STREAM (stream));
+
+found:
+ swfdec_audio_add (SWFDEC_AUDIO (stream), player);
+ check (SWFDEC_AUDIO (stream));
+ return SWFDEC_AUDIO (stream);
+}
+
diff --git a/swfdec/swfdec_audio_swf_stream.h b/swfdec/swfdec_audio_swf_stream.h
new file mode 100644
index 0000000..e310a29
--- /dev/null
+++ b/swfdec/swfdec_audio_swf_stream.h
@@ -0,0 +1,59 @@
+/* Swfdec
+ * Copyright (C) 2008 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_AUDIO_SWF_STREAM_H_
+#define _SWFDEC_AUDIO_SWF_STREAM_H_
+
+#include <swfdec/swfdec_audio_stream.h>
+#include <swfdec/swfdec_sprite.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecAudioSwfStream SwfdecAudioSwfStream;
+typedef struct _SwfdecAudioSwfStreamClass SwfdecAudioSwfStreamClass;
+
+#define SWFDEC_TYPE_AUDIO_SWF_STREAM (swfdec_audio_swf_stream_get_type())
+#define SWFDEC_IS_AUDIO_SWF_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AUDIO_SWF_STREAM))
+#define SWFDEC_IS_AUDIO_SWF_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AUDIO_SWF_STREAM))
+#define SWFDEC_AUDIO_SWF_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AUDIO_SWF_STREAM, SwfdecAudioSwfStream))
+#define SWFDEC_AUDIO_SWF_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AUDIO_SWF_STREAM, SwfdecAudioSwfStreamClass))
+#define SWFDEC_AUDIO_SWF_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AUDIO_SWF_STREAM, SwfdecAudioSwfStreamClass))
+
+struct _SwfdecAudioSwfStream
+{
+ SwfdecAudioStream stream;
+
+ SwfdecSprite * sprite; /* sprite we play audio in */
+ guint id; /* if of next tag in sprite we need to decode */
+};
+
+struct _SwfdecAudioSwfStreamClass
+{
+ SwfdecAudioStreamClass stream_class;
+};
+
+GType swfdec_audio_swf_stream_get_type (void);
+
+SwfdecAudio * swfdec_audio_swf_stream_new (SwfdecPlayer * player,
+ SwfdecSprite * sprite,
+ guint id);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_codec_gst.h b/swfdec/swfdec_codec_gst.h
new file mode 100644
index 0000000..1cb719e
--- /dev/null
+++ b/swfdec/swfdec_codec_gst.h
@@ -0,0 +1,59 @@
+/* Swfdec
+ * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
+ * 2005-2006 Eric Anholt <eric at anholt.net>
+ * 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_GST_H__
+#define __SWFDEC_CODEC_GST_H__
+
+#include <gst/gst.h>
+#include <swfdec/swfdec.h>
+
+
+typedef struct {
+ GstElement * bin;
+ GstPad * src;
+ GstPad * sink;
+ GQueue * queue; /* all the stored output GstBuffers */
+} SwfdecGstDecoder;
+
+gboolean swfdec_gst_decoder_init (SwfdecGstDecoder * dec,
+ GstCaps * srccaps,
+ GstCaps * sinkcaps,
+ ...) G_GNUC_NULL_TERMINATED;
+void swfdec_gst_decoder_push_eos (SwfdecGstDecoder * dec);
+GstBuffer * swfdec_gst_decoder_pull (SwfdecGstDecoder * dec);
+gboolean swfdec_gst_decoder_push (SwfdecGstDecoder * dec,
+ GstBuffer * buffer);
+void swfdec_gst_decoder_finish (SwfdecGstDecoder * dec);
+
+
+/* NB: references argument more than once */
+#define swfdec_buffer_new_from_gst(buffer) \
+ swfdec_buffer_new_full (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), \
+ (SwfdecBufferFreeFunc) gst_mini_object_unref, (buffer))
+GstBuffer * swfdec_gst_buffer_new (SwfdecBuffer * buffer);
+
+
+GstElementFactory *
+ swfdec_gst_get_element_factory (GstCaps * caps);
+
+
+#endif
+
diff --git a/swfdec/swfdec_sound.c b/swfdec/swfdec_sound.c
index 88cb175..cc5862b 100644
--- a/swfdec/swfdec_sound.c
+++ b/swfdec/swfdec_sound.c
@@ -64,46 +64,6 @@ swfdec_sound_init (SwfdecSound * sound)
}
int
-tag_func_sound_stream_block (SwfdecSwfDecoder * s, guint tag)
-{
- SwfdecSound *sound;
- SwfdecBuffer *chunk;
- int n_samples;
- int skip;
-
- sound = SWFDEC_SOUND (s->parse_sprite->frames[s->parse_sprite->parse_frame].sound_head);
-
- if (!sound) {
- SWFDEC_WARNING ("no streaming sound block");
- return SWFDEC_STATUS_OK;
- }
-
- n_samples = swfdec_bits_get_u16 (&s->b);
- if (sound->codec == SWFDEC_AUDIO_CODEC_MP3) {
- skip = swfdec_bits_get_s16 (&s->b);
- } else {
- skip = 0;
- }
- if (swfdec_bits_left (&s->b) == 0) {
- SWFDEC_DEBUG ("empty sound block n_samples=%d skip=%d", n_samples,
- skip);
- chunk = NULL;
- return SWFDEC_STATUS_OK;
- } else {
- chunk = swfdec_bits_get_buffer (&s->b, -1);
- g_assert (chunk != NULL);
- SWFDEC_LOG ("got a buffer with %u samples, %d skip and %"G_GSIZE_FORMAT" bytes mp3 data", n_samples, skip,
- chunk->length);
- /* use this to write out the stream data to stdout - nice way to get an mp3 file :) */
- //write (1, (void *) chunk->data, chunk->length);
- }
-
- swfdec_sprite_add_sound_chunk (s->parse_sprite, s->parse_sprite->parse_frame, chunk, skip, n_samples);
-
- return SWFDEC_STATUS_OK;
-}
-
-int
tag_func_define_sound (SwfdecSwfDecoder * s, guint tag)
{
SwfdecBits *b = &s->b;
@@ -219,61 +179,6 @@ swfdec_sound_get_decoded (SwfdecSound *sound)
return sound->decoded;
}
-int
-tag_func_sound_stream_head (SwfdecSwfDecoder * s, guint tag)
-{
- SwfdecBits *b = &s->b;
- SwfdecAudioFormat playback;
- guint playback_codec;
- int n_samples;
- int latency;
- SwfdecSound *sound;
-
- playback_codec = swfdec_bits_getbits (b, 4);
- /* we don't care about playback suggestions */
- playback = swfdec_audio_format_parse (b);
- SWFDEC_LOG (" suggested playback format: %s", swfdec_audio_format_to_string (playback));
-
- sound = g_object_new (SWFDEC_TYPE_SOUND, NULL);
- sound->codec = swfdec_bits_getbits (b, 4);
- sound->format = swfdec_audio_format_parse (b);
- n_samples = swfdec_bits_get_u16 (b);
- if (playback_codec != 0 && playback_codec != sound->codec) {
- SWFDEC_FIXME ("playback codec %u doesn't match sound codec %u",
- playback_codec, sound->codec);
- }
-
- if (s->parse_sprite->frames[s->parse_sprite->parse_frame].sound_head)
- g_object_unref (s->parse_sprite->frames[s->parse_sprite->parse_frame].sound_head);
- s->parse_sprite->frames[s->parse_sprite->parse_frame].sound_head = sound;
-
- switch (sound->codec) {
- case SWFDEC_AUDIO_CODEC_UNDEFINED:
- if (swfdec_audio_format_is_16bit (sound->format)) {
- SWFDEC_WARNING ("undefined endianness for s16 sound");
- /* just assume LE and hope it works (FIXME: want a switch for this?) */
- sound->codec = SWFDEC_AUDIO_CODEC_UNCOMPRESSED;
- }
- break;
- case SWFDEC_AUDIO_CODEC_MP3:
- /* latency seek */
- latency = swfdec_bits_get_s16 (b);
- break;
- case SWFDEC_AUDIO_CODEC_ADPCM:
- case SWFDEC_AUDIO_CODEC_UNCOMPRESSED:
- case SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ:
- case SWFDEC_AUDIO_CODEC_NELLYMOSER:
- break;
- default:
- SWFDEC_WARNING ("unknown codec %d", sound->codec);
- sound->codec = SWFDEC_AUDIO_CODEC_UNDEFINED;
- }
-
- swfdec_decoder_use_audio_codec (SWFDEC_DECODER (s), sound->codec, sound->format);
-
- return SWFDEC_STATUS_OK;
-}
-
void
swfdec_sound_chunk_free (SwfdecSoundChunk *chunk)
{
diff --git a/swfdec/swfdec_sound.h b/swfdec/swfdec_sound.h
index f3de014..928e770 100644
--- a/swfdec/swfdec_sound.h
+++ b/swfdec/swfdec_sound.h
@@ -79,8 +79,6 @@ struct _SwfdecSoundClass
GType swfdec_sound_get_type (void);
int tag_func_define_sound (SwfdecSwfDecoder * s, guint tag);
-int tag_func_sound_stream_block (SwfdecSwfDecoder * s, guint tag);
-int tag_func_sound_stream_head (SwfdecSwfDecoder * s, guint tag);
int tag_func_start_sound (SwfdecSwfDecoder * s, guint tag);
int tag_func_define_button_sound (SwfdecSwfDecoder * s, guint tag);
diff --git a/swfdec/swfdec_sprite.c b/swfdec/swfdec_sprite.c
index 0a06bb0..fe6386d 100644
--- a/swfdec/swfdec_sprite.c
+++ b/swfdec/swfdec_sprite.c
@@ -46,13 +46,6 @@ swfdec_sprite_dispose (GObject *object)
for (i = 0; i < sprite->n_frames; i++) {
g_slist_foreach (sprite->frames[i].labels, (GFunc) g_free, NULL);
g_slist_free (sprite->frames[i].labels);
- if (sprite->frames[i].sound_head)
- g_object_unref (sprite->frames[i].sound_head);
- if (sprite->frames[i].sound_block) {
- swfdec_buffer_unref (sprite->frames[i].sound_block);
- }
- g_slist_foreach (sprite->frames[i].sound, (GFunc) swfdec_sound_chunk_free, NULL);
- g_slist_free (sprite->frames[i].sound);
}
g_free(sprite->frames);
}
@@ -72,31 +65,6 @@ swfdec_sprite_dispose (GObject *object)
}
void
-swfdec_sprite_add_sound_chunk (SwfdecSprite * sprite, guint frame,
- SwfdecBuffer * chunk, int skip, guint n_samples)
-{
- g_assert (sprite->frames != NULL);
- g_assert (chunk != NULL || n_samples == 0);
-
- if (sprite->frames[frame].sound_head == NULL) {
- SWFDEC_ERROR ("attempting to add a sound block without previous sound head");
- swfdec_buffer_unref (chunk);
- return;
- }
- if (sprite->frames[frame].sound_block) {
- SWFDEC_ERROR ("attempting to add 2 sound blocks to one frame");
- swfdec_buffer_unref (chunk);
- return;
- }
- SWFDEC_LOG ("adding %u samples in %"G_GSIZE_FORMAT" bytes to frame %u", n_samples,
- chunk ? chunk->length : 0, frame);
- sprite->frames[frame].sound_skip = skip;
- sprite->frames[frame].sound_block = chunk;
- sprite->frames[frame].sound_samples = n_samples *
- swfdec_audio_format_get_granularity (sprite->frames[frame].sound_head->format);
-}
-
-void
swfdec_sprite_add_action (SwfdecSprite *sprite, guint tag, SwfdecBuffer *buffer)
{
SwfdecSpriteAction action;
@@ -123,14 +91,6 @@ swfdec_sprite_get_action (SwfdecSprite *sprite, guint n, guint *tag, SwfdecBuffe
return TRUE;
}
-int
-tag_func_set_background_color (SwfdecSwfDecoder * s, guint tag)
-{
- s->parse_sprite->bgcolor = swfdec_bits_get_color (&s->b);
-
- return SWFDEC_STATUS_OK;
-}
-
static SwfdecMovie *
swfdec_sprite_create_movie (SwfdecGraphic *graphic, gsize *size)
{
@@ -164,18 +124,11 @@ void
swfdec_sprite_set_n_frames (SwfdecSprite *sprite, guint n_frames,
guint rate)
{
- guint i;
-
g_return_if_fail (SWFDEC_IS_SPRITE (sprite));
+
if (n_frames > 0) {
sprite->frames = g_new0 (SwfdecSpriteFrame, n_frames);
sprite->n_frames = n_frames;
-
- if (rate > 0) {
- for (i = 0; i < n_frames; i++) {
- sprite->frames[i].sound_samples = 44100 * 256 / rate;
- }
- }
}
SWFDEC_LOG ("n_frames = %d", sprite->n_frames);
diff --git a/swfdec/swfdec_sprite.h b/swfdec/swfdec_sprite.h
index ae1d035..fda54f0 100644
--- a/swfdec/swfdec_sprite.h
+++ b/swfdec/swfdec_sprite.h
@@ -52,13 +52,6 @@ struct _SwfdecSpriteAction {
struct _SwfdecSpriteFrame
{
GSList *labels; /* names of the frame for "GotoLabel" */
-
- /* sound */
- SwfdecSound *sound_head; /* sound head for this frame */
- int sound_skip; /* samples to skip - maybe even backwards */
- SwfdecBuffer *sound_block; /* sound chunk to play here or NULL for none */
- guint sound_samples; /* number of samples in this frame */
- GSList *sound; /* list of SwfdecSoundChunk events to start playing here */
};
struct _SwfdecSprite
@@ -69,7 +62,6 @@ struct _SwfdecSprite
guint n_frames; /* number of frames in this sprite */
SwfdecScript * init_action; /* action to run when initializing this sprite */
GArray * actions; /* SwfdecSpriteAction in execution order */
- SwfdecColor bgcolor; /* background color for this sprite */
/* parse state */
guint parse_frame; /* frame we're currently parsing. == n_frames if done parsing */
@@ -93,8 +85,7 @@ gboolean swfdec_sprite_get_action (SwfdecSprite * sprite,
SwfdecBuffer ** buffer);
int swfdec_sprite_get_frame (SwfdecSprite * sprite,
const char * label);
-
-int tag_func_set_background_color (SwfdecSwfDecoder * s, guint tag);
+#define swfdec_sprite_is_loaded(sprite) ((sprite)->parse_frame == (sprite)->n_frames)
G_END_DECLS
diff --git a/swfdec/swfdec_sprite_movie.c b/swfdec/swfdec_sprite_movie.c
index 9bc8efa..f2bc22e 100644
--- a/swfdec/swfdec_sprite_movie.c
+++ b/swfdec/swfdec_sprite_movie.c
@@ -26,6 +26,7 @@
#include "swfdec_sprite_movie.h"
#include "swfdec_as_internal.h"
#include "swfdec_as_strings.h"
+#include "swfdec_audio_swf_stream.h"
#include "swfdec_audio_event.h"
#include "swfdec_audio_stream.h"
#include "swfdec_debug.h"
@@ -412,7 +413,8 @@ swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, guint tag, Swf
}
return TRUE;
case SWFDEC_TAG_STARTSOUND:
- if (!fast_forward) swfdec_sprite_movie_start_sound (mov, &bits);
+ if (!fast_forward)
+ swfdec_sprite_movie_start_sound (mov, &bits);
return TRUE;
case SWFDEC_TAG_SHOWFRAME:
if (movie->frame < movie->n_frames) {
@@ -484,6 +486,17 @@ swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, guint tag, Swf
}
}
return TRUE;
+ case SWFDEC_TAG_SOUNDSTREAMHEAD:
+ case SWFDEC_TAG_SOUNDSTREAMHEAD2:
+ /* ignore, those are handled by the sound stream */
+ return TRUE;
+ case SWFDEC_TAG_SOUNDSTREAMBLOCK:
+ if (!fast_forward) {
+ if (movie->sound_stream == NULL)
+ movie->sound_stream = swfdec_audio_swf_stream_new (player, movie->sprite, tag);
+ movie->sound_active = TRUE;
+ }
+ return TRUE;
default:
g_assert_not_reached ();
return FALSE;
@@ -527,6 +540,7 @@ swfdec_sprite_movie_goto (SwfdecSpriteMovie *movie, guint goto_frame)
SwfdecPlayer *player;
GList *old;
guint n;
+ gboolean remove_audio;
g_return_if_fail (SWFDEC_IS_SPRITE_MOVIE (movie));
@@ -567,11 +581,21 @@ swfdec_sprite_movie_goto (SwfdecSpriteMovie *movie, guint goto_frame)
mov->list = g_list_concat (mov->list, walk);
n = goto_frame;
movie->next_action = 0;
+ remove_audio = TRUE;
} else {
/* NB: this path is also taken on init */
old = NULL;
n = goto_frame - movie->frame;
+ remove_audio = n > 1;
}
+ /* remove audio after seeks */
+ if (remove_audio && movie->sound_stream) {
+ swfdec_audio_remove (movie->sound_stream);
+ g_object_unref (movie->sound_stream);
+ movie->sound_stream = NULL;
+ }
+ remove_audio = !movie->sound_active;
+ movie->sound_active = FALSE;
while (n) {
guint tag;
gboolean first_time;
@@ -627,6 +651,13 @@ out:
}
g_list_free (old);
}
+
+ /* after two frames without SoundStreamBlock, audio apparently gets removed */
+ if (!movie->sound_active && remove_audio && movie->sound_stream != NULL) {
+ swfdec_audio_remove (movie->sound_stream);
+ g_object_unref (movie->sound_stream);
+ movie->sound_stream = NULL;
+ }
}
/*** MOVIE ***/
@@ -688,66 +719,6 @@ swfdec_sprite_movie_iterate (SwfdecActor *actor)
}
}
-/* FIXME: This function is a mess */
-static gboolean
-swfdec_sprite_movie_iterate_end (SwfdecActor *actor)
-{
- SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (actor);
- SwfdecSpriteFrame *last;
- SwfdecSpriteFrame *current;
- SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (actor)->context);
-
- if (!SWFDEC_ACTOR_CLASS (swfdec_sprite_movie_parent_class)->iterate_end (actor))
- return FALSE;
-
- if (movie->sprite == NULL)
- return TRUE;
- g_assert (movie->frame <= movie->n_frames);
- if (movie->frame == 0)
- return TRUE;
- current = &movie->sprite->frames[movie->frame - 1];
-
- /* then do the streaming thing */
- if (current->sound_head == NULL ||
- !movie->playing) {
- if (movie->sound_stream) {
- swfdec_audio_remove (movie->sound_stream);
- g_object_unref (movie->sound_stream);
- movie->sound_stream = NULL;
- }
- goto exit;
- }
- if (movie->sound_stream == NULL && current->sound_block == NULL)
- goto exit;
- SWFDEC_LOG ("iterating audio (from %u to %u)", movie->sound_frame, movie->frame);
- if (movie->sound_frame + 1 != movie->frame)
- goto new_decoder;
- if (movie->sound_frame == (guint) -1)
- goto new_decoder;
- if (current->sound_head && movie->sound_stream == NULL)
- goto new_decoder;
- last = &movie->sprite->frames[movie->sound_frame];
- if (last->sound_head != current->sound_head)
- goto new_decoder;
-exit:
- movie->sound_frame = movie->frame;
- return TRUE;
-
-new_decoder:
- if (movie->sound_stream) {
- swfdec_audio_remove (movie->sound_stream);
- g_object_unref (movie->sound_stream);
- movie->sound_stream = NULL;
- }
-
- if (current->sound_block) {
- movie->sound_stream = swfdec_audio_stream_new (player,
- movie->sprite, movie->frame - 1);
- movie->sound_frame = movie->frame;
- }
- return TRUE;
-}
-
static void
swfdec_sprite_movie_finish_movie (SwfdecMovie *mov)
{
@@ -793,7 +764,6 @@ swfdec_sprite_movie_class_init (SwfdecSpriteMovieClass * g_class)
movie_class->finish_movie = swfdec_sprite_movie_finish_movie;
actor_class->iterate_start = swfdec_sprite_movie_iterate;
- actor_class->iterate_end = swfdec_sprite_movie_iterate_end;
}
static void
diff --git a/swfdec/swfdec_sprite_movie.h b/swfdec/swfdec_sprite_movie.h
index 41cf451..4ab6145 100644
--- a/swfdec/swfdec_sprite_movie.h
+++ b/swfdec/swfdec_sprite_movie.h
@@ -50,8 +50,8 @@ struct _SwfdecSpriteMovie
gboolean playing; /* TRUE if the movie automatically advances */
/* audio stream handling */
- guint sound_frame; /* current sound frame */
SwfdecAudio * sound_stream; /* stream that currently plays */
+ gboolean sound_active; /* if the sound stream had a SoundStreamBlock last frame */
};
struct _SwfdecSpriteMovieClass
diff --git a/swfdec/swfdec_tag.c b/swfdec/swfdec_tag.c
index c9e4512..9e4fd4a 100644
--- a/swfdec/swfdec_tag.c
+++ b/swfdec/swfdec_tag.c
@@ -292,12 +292,6 @@ tag_func_show_frame (SwfdecSwfDecoder * s, guint tag)
SWFDEC_CHARACTER (s->parse_sprite)->id);
s->parse_sprite->parse_frame++;
- if (s->parse_sprite->parse_frame < s->parse_sprite->n_frames) {
- SwfdecSpriteFrame *old = &s->parse_sprite->frames[s->parse_sprite->parse_frame - 1];
- SwfdecSpriteFrame *new = &s->parse_sprite->frames[s->parse_sprite->parse_frame];
- if (old->sound_head)
- new->sound_head = g_object_ref (old->sound_head);
- }
tag_func_enqueue (s, tag);
return SWFDEC_STATUS_IMAGE;
@@ -352,6 +346,34 @@ tag_func_do_init_action (SwfdecSwfDecoder * s, guint tag)
return SWFDEC_STATUS_OK;
}
+/* only needed for the codec finding stuff */
+static int
+tag_func_sound_stream_head (SwfdecSwfDecoder *s, guint tag)
+{
+ SwfdecBits bits;
+ SwfdecAudioFormat playback_format, format;
+ guint playback_codec, codec;
+ int n_samples;
+
+ bits = s->b;
+
+ /* we don't care about playback suggestions */
+ playback_codec = swfdec_bits_getbits (&bits, 4);
+ playback_format = swfdec_audio_format_parse (&bits);
+ SWFDEC_LOG (" suggested playback format: %s", swfdec_audio_format_to_string (playback_format));
+
+ codec = swfdec_bits_getbits (&bits, 4);
+ format = swfdec_audio_format_parse (&bits);
+ n_samples = swfdec_bits_get_u16 (&bits);
+ SWFDEC_LOG (" codec: %u", codec);
+ SWFDEC_LOG (" format: %s", swfdec_audio_format_to_string (format));
+ SWFDEC_LOG (" samples: %u", n_samples);
+
+ swfdec_decoder_use_audio_codec (SWFDEC_DECODER (s), codec, format);
+
+ return tag_func_enqueue (s, tag);
+}
+
struct tag_func_struct
{
const char *name;
@@ -379,7 +401,7 @@ static struct tag_func_struct tag_funcs[] = {
[SWFDEC_TAG_DEFINEBUTTONSOUND] =
{"DefineButtonSound", tag_func_define_button_sound, 0},
[SWFDEC_TAG_SOUNDSTREAMHEAD] = {"SoundStreamHead", tag_func_sound_stream_head, SWFDEC_TAG_DEFINE_SPRITE },
- [SWFDEC_TAG_SOUNDSTREAMBLOCK] = {"SoundStreamBlock", tag_func_sound_stream_block, SWFDEC_TAG_DEFINE_SPRITE },
+ [SWFDEC_TAG_SOUNDSTREAMBLOCK] = {"SoundStreamBlock", tag_func_enqueue, SWFDEC_TAG_DEFINE_SPRITE },
[SWFDEC_TAG_DEFINEBITSLOSSLESS] =
{"DefineBitsLossless", tag_func_define_bits_lossless, 0},
[SWFDEC_TAG_DEFINEBITSJPEG2] = {"DefineBitsJPEG2", tag_func_define_bits_jpeg_2, 0},
commit cfff18382cf89249781572322d0c180c964449c0
Author: Benjamin Otte <otte at gnome.org>
Date: Tue May 27 14:50:42 2008 +0200
avoid audioresample element at all costs, it is way too slow
diff --git a/swfdec/swfdec_audio_decoder_gst.c b/swfdec/swfdec_audio_decoder_gst.c
index 3f94e7e..73f4d06 100644
--- a/swfdec/swfdec_audio_decoder_gst.c
+++ b/swfdec/swfdec_audio_decoder_gst.c
@@ -114,11 +114,35 @@ swfdec_audio_decoder_gst_init (SwfdecAudioDecoderGst *audio_decoder_gst)
{
}
+static const char *
+swfdec_audio_decoder_get_resampler (void)
+{
+ /* FIXME: This is hardcoded as there's no autopluggable way to get the
+ * best resampler by rank.
+ * Even if there were, audioresample (which has the highest rank) is so slow
+ * it takes roughly a second to resample stuff that ffaudioresample does in
+ * 0.05 seconds.
+ */
+ static const char *options[] = { "ffaudioresample", "speexresample", "audioresample" };
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (options); i++) {
+ GstElementFactory *factory = gst_element_factory_find (options[i]);
+ if (factory) {
+ gst_object_unref (factory);
+ return options[i];
+ }
+ }
+ SWFDEC_ERROR ("no resampling element found. Check that GStreamer's base plugins are installed.");
+ return NULL;
+}
+
SwfdecAudioDecoder *
swfdec_audio_decoder_gst_new (guint type, SwfdecAudioFormat format)
{
SwfdecAudioDecoderGst *player;
GstCaps *srccaps, *sinkcaps;
+ const char *resample;
srccaps = swfdec_audio_decoder_get_caps (type, format);
if (srccaps == NULL)
@@ -129,8 +153,11 @@ swfdec_audio_decoder_gst_new (guint type, SwfdecAudioFormat format)
/* create decoder */
sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, rate=44100, channels=2");
g_assert (sinkcaps);
+ resample = swfdec_audio_decoder_get_resampler ();
+ if (resample == NULL)
+ goto error;
if (!swfdec_gst_decoder_init (&player->dec, srccaps, sinkcaps,
- "audioconvert", "audioresample", NULL))
+ "audioconvert", resample, NULL))
goto error;
gst_caps_unref (srccaps);
commit de0a095981b46170fe1331c75312473895fbc75b
Author: Benjamin Otte <otte at gnome.org>
Date: Tue May 27 12:00:39 2008 +0200
update GStreamer decoder to properly link audioconvert and audioscale
diff --git a/swfdec/swfdec_audio_decoder_gst.c b/swfdec/swfdec_audio_decoder_gst.c
index 45cbc90..3f94e7e 100644
--- a/swfdec/swfdec_audio_decoder_gst.c
+++ b/swfdec/swfdec_audio_decoder_gst.c
@@ -71,20 +71,8 @@ swfdec_audio_decoder_gst_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
swfdec_buffer_ref (buffer);
buf = swfdec_gst_buffer_new (buffer);
if (!swfdec_gst_decoder_push (&player->dec, buf))
- goto error;
+ swfdec_audio_decoder_error (dec, "error pushing");
}
- while ((buf = swfdec_gst_decoder_pull (&player->dec))) {
- if (!swfdec_gst_decoder_push (&player->convert, buf))
- goto error;
- }
- while ((buf = swfdec_gst_decoder_pull (&player->convert))) {
- if (!swfdec_gst_decoder_push (&player->resample, buf))
- goto error;
- }
- return;
-
-error:
- swfdec_audio_decoder_error (dec, "error pushing");
}
static SwfdecBuffer *
@@ -93,7 +81,7 @@ swfdec_audio_decoder_gst_pull (SwfdecAudioDecoder *dec)
SwfdecAudioDecoderGst *player = SWFDEC_AUDIO_DECODER_GST (dec);
GstBuffer *buf;
- buf = swfdec_gst_decoder_pull (&player->resample);
+ buf = swfdec_gst_decoder_pull (&player->dec);
if (buf == NULL)
return NULL;
return swfdec_buffer_new_from_gst (buf);
@@ -105,8 +93,6 @@ swfdec_audio_decoder_gst_dispose (GObject *object)
SwfdecAudioDecoderGst *player = (SwfdecAudioDecoderGst *) object;
swfdec_gst_decoder_finish (&player->dec);
- swfdec_gst_decoder_finish (&player->convert);
- swfdec_gst_decoder_finish (&player->resample);
G_OBJECT_CLASS (swfdec_audio_decoder_gst_parent_class)->dispose (object);
}
@@ -141,25 +127,11 @@ swfdec_audio_decoder_gst_new (guint type, SwfdecAudioFormat format)
player = g_object_new (SWFDEC_TYPE_AUDIO_DECODER_GST, NULL);
/* create decoder */
- sinkcaps = gst_caps_from_string ("audio/x-raw-int");
- g_assert (sinkcaps);
- if (!swfdec_gst_decoder_init (&player->dec, NULL, srccaps, sinkcaps))
- goto error;
- /* create audioconvert */
- gst_caps_unref (srccaps);
- srccaps = sinkcaps;
- sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, channels=2");
- g_assert (sinkcaps);
- if (!swfdec_gst_decoder_init (&player->convert, "audioconvert", srccaps, sinkcaps))
- goto error;
- /* create audiorate */
- gst_caps_unref (srccaps);
- srccaps = sinkcaps;
sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, rate=44100, channels=2");
g_assert (sinkcaps);
- if (!swfdec_gst_decoder_init (&player->resample, "audioresample", srccaps, sinkcaps))
+ if (!swfdec_gst_decoder_init (&player->dec, srccaps, sinkcaps,
+ "audioconvert", "audioresample", NULL))
goto error;
- g_object_set_data (G_OBJECT (player->resample.sink), "swfdec-player", player);
gst_caps_unref (srccaps);
gst_caps_unref (sinkcaps);
diff --git a/swfdec/swfdec_audio_decoder_gst.h b/swfdec/swfdec_audio_decoder_gst.h
index 284eb0c..18fd146 100644
--- a/swfdec/swfdec_audio_decoder_gst.h
+++ b/swfdec/swfdec_audio_decoder_gst.h
@@ -41,8 +41,6 @@ struct _SwfdecAudioDecoderGst
SwfdecAudioDecoder decoder;
SwfdecGstDecoder dec; /* the actual decoder */
- SwfdecGstDecoder convert; /* audioconvert element to got to S16 stereo */
- SwfdecGstDecoder resample; /* resampler to 44100Hz */
};
struct _SwfdecAudioDecoderGstClass
diff --git a/swfdec/swfdec_codec_gst.c b/swfdec/swfdec_codec_gst.c
index 054d06c..7414180 100644
--- a/swfdec/swfdec_codec_gst.c
+++ b/swfdec/swfdec_codec_gst.c
@@ -213,31 +213,52 @@ swfdec_gst_chain_func (GstPad *pad, GstBuffer *buffer)
}
gboolean
-swfdec_gst_decoder_init (SwfdecGstDecoder *dec, const char *name, GstCaps *srccaps, GstCaps *sinkcaps)
+swfdec_gst_decoder_init (SwfdecGstDecoder *dec, GstCaps *srccaps, GstCaps *sinkcaps, ...)
{
- if (name) {
- dec->decoder = gst_element_factory_make (name, "decoder");
- } else {
- GstElementFactory *factory = swfdec_gst_get_element_factory (srccaps);
- if (factory) {
- dec->decoder = gst_element_factory_create (factory, "decoder");
- gst_object_unref (factory);
- }
+ va_list args;
+ GstElementFactory *factory;
+ GstElement *decoder;
+ const char *name;
+
+ /* create decoder */
+ factory = swfdec_gst_get_element_factory (srccaps);
+ dec->bin = gst_bin_new ("bin");
+ if (factory) {
+ decoder = gst_element_factory_create (factory, "decoder");
+ gst_object_unref (factory);
}
- if (dec->decoder == NULL) {
+ if (decoder == NULL) {
SWFDEC_ERROR ("failed to create decoder");
return FALSE;
}
- dec->src = swfdec_gst_connect_srcpad (dec->decoder, srccaps);
+ gst_bin_add (GST_BIN (dec->bin), decoder);
+ dec->src = swfdec_gst_connect_srcpad (decoder, srccaps);
if (dec->src == NULL)
return FALSE;
- dec->sink = swfdec_gst_connect_sinkpad (dec->decoder, sinkcaps);
+
+ /* plug transform elements */
+ va_start (args, sinkcaps);
+ while ((name = va_arg (args, const char *))) {
+ GstElement *next = gst_element_factory_make (name, NULL);
+ if (next == NULL) {
+ SWFDEC_ERROR ("failed to create '%s' element", name);
+ return FALSE;
+ }
+ gst_bin_add (GST_BIN (dec->bin), next);
+ if (!gst_element_link (decoder, next)) {
+ SWFDEC_ERROR ("failed to link '%s' element to decoder", name);
+ return FALSE;
+ }
+ decoder = next;
+ }
+ va_end (args);
+ dec->sink = swfdec_gst_connect_sinkpad (decoder, sinkcaps);
if (dec->sink == NULL)
return FALSE;
gst_pad_set_chain_function (dec->sink, swfdec_gst_chain_func);
dec->queue = g_queue_new ();
g_object_set_data (G_OBJECT (dec->sink), "swfdec-queue", dec->queue);
- if (!gst_element_set_state (dec->decoder, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS) {
+ if (!gst_element_set_state (dec->bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS) {
SWFDEC_ERROR ("could not change element state");
return FALSE;
}
@@ -247,10 +268,10 @@ swfdec_gst_decoder_init (SwfdecGstDecoder *dec, const char *name, GstCaps *srcca
void
swfdec_gst_decoder_finish (SwfdecGstDecoder *dec)
{
- if (dec->decoder) {
- gst_element_set_state (dec->decoder, GST_STATE_NULL);
- g_object_unref (dec->decoder);
- dec->decoder = NULL;
+ if (dec->bin) {
+ gst_element_set_state (dec->bin, GST_STATE_NULL);
+ g_object_unref (dec->bin);
+ dec->bin = NULL;
}
if (dec->src) {
g_object_unref (dec->src);
@@ -437,7 +458,7 @@ swfdec_video_decoder_gst_new (guint codec)
player->decoder.decode = swfdec_video_decoder_gst_decode;
player->decoder.free = swfdec_video_decoder_gst_free;
- if (!swfdec_gst_decoder_init (&player->dec, NULL, srccaps, sinkcaps)) {
+ if (!swfdec_gst_decoder_init (&player->dec, srccaps, sinkcaps, NULL)) {
swfdec_video_decoder_gst_free (&player->decoder);
gst_caps_unref (srccaps);
gst_caps_unref (sinkcaps);
commit 4b91a1ab591e31c8d02d7bc0135a14e5fadb8df9
Author: Benjamin Otte <otte at gnome.org>
Date: Tue May 27 11:59:29 2008 +0200
update tools for API changes
diff --git a/tools/dump.c b/tools/dump.c
index 87a03f2..0c83728 100644
--- a/tools/dump.c
+++ b/tools/dump.c
@@ -30,6 +30,7 @@
#include <glib.h>
#include <glib-object.h>
#include <swfdec/swfdec.h>
+#include <swfdec/swfdec_audio_decoder.h>
#include <swfdec/swfdec_button.h>
#include <swfdec/swfdec_text_field.h>
#include <swfdec/swfdec_font.h>
commit cfaacc63a95c8fc718d3572abd7af76f69a5841e
Author: Benjamin Otte <otte at gnome.org>
Date: Mon May 26 13:12:42 2008 +0200
make audio decoders real objects
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 713c2f4..33edc71 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -1,9 +1,9 @@
SUBDIRS = jpeg
-CODECS =
+CODEC_FILES =
if HAVE_GST
-CODECS += swfdec_codec_gst.c
+CODEC_FILES += swfdec_codec_gst.c swfdec_audio_decoder_gst.c
endif
lib_LTLIBRARIES = libswfdec- at SWFDEC_MAJORMINOR@.la
@@ -33,6 +33,10 @@ libswfdec_source_files = \
swfdec_as_types.c \
swfdec_asbroadcaster.c \
swfdec_audio.c \
+ swfdec_audio_decoder.c \
+ swfdec_audio_decoder_adpcm.c \
+ swfdec_audio_decoder_uncompressed.c \
+ $(CODEC_FILES) \
swfdec_audio_event.c \
swfdec_audio_flv.c \
swfdec_audio_stream.c \
@@ -52,9 +56,6 @@ libswfdec_source_files = \
swfdec_cached_video.c \
swfdec_camera.c \
swfdec_character.c \
- swfdec_codec_adpcm.c \
- swfdec_codec_audio.c \
- $(CODECS) \
swfdec_codec_screen.c \
swfdec_codec_video.c \
swfdec_codec_vp6_alpha.c \
@@ -226,6 +227,10 @@ noinst_HEADERS = \
swfdec_as_super.h \
swfdec_asnative.h \
swfdec_audio_internal.h \
+ swfdec_audio_decoder.h \
+ swfdec_audio_decoder_adpcm.h \
+ swfdec_audio_decoder_gst.h \
+ swfdec_audio_decoder_uncompressed.h \
swfdec_audio_event.h \
swfdec_audio_flv.h \
swfdec_audio_stream.h \
@@ -238,7 +243,7 @@ noinst_HEADERS = \
swfdec_cached_image.h \
swfdec_cached_video.h \
swfdec_character.h \
- swfdec_codec_audio.h \
+ swfdec_codec_gst.h \
swfdec_codec_video.h \
swfdec_color.h \
swfdec_constant_pool.h \
diff --git a/swfdec/swfdec_audio_decoder.c b/swfdec/swfdec_audio_decoder.c
new file mode 100644
index 0000000..90d2b36
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder.c
@@ -0,0 +1,219 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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_audio_decoder.h"
+#include "swfdec_audio_decoder_adpcm.h"
+#include "swfdec_audio_decoder_gst.h"
+#include "swfdec_audio_decoder_uncompressed.h"
+#include "swfdec_debug.h"
+#include "swfdec_internal.h"
+
+G_DEFINE_TYPE (SwfdecAudioDecoder, swfdec_audio_decoder, G_TYPE_OBJECT)
+
+static void
+swfdec_audio_decoder_class_init (SwfdecAudioDecoderClass *klass)
+{
+}
+
+static void
+swfdec_audio_decoder_init (SwfdecAudioDecoder *audio_decoder)
+{
+}
+
+static SwfdecAudioDecoder *
+swfdec_audio_decoder_builtin_new (guint codec, SwfdecAudioFormat format)
+{
+ switch (format) {
+ case SWFDEC_AUDIO_CODEC_UNDEFINED:
+ case SWFDEC_AUDIO_CODEC_UNCOMPRESSED:
+ return g_object_new (SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED, NULL);
+ case SWFDEC_AUDIO_CODEC_ADPCM:
+ return g_object_new (SWFDEC_TYPE_AUDIO_DECODER_ADPCM, NULL);
+ default:
+ return NULL;
+ }
+}
+
+static gboolean
+swfdec_audio_decoder_builtin_prepare (guint codec, SwfdecAudioFormat format, char **detail)
+{
+ return codec == SWFDEC_AUDIO_CODEC_UNCOMPRESSED ||
+ codec == SWFDEC_AUDIO_CODEC_UNDEFINED ||
+ codec == SWFDEC_AUDIO_CODEC_ADPCM;
+}
+
+static const struct {
+ const char * name;
+ SwfdecAudioDecoder * (* func) (guint, SwfdecAudioFormat);
+ gboolean (* prepare) (guint, SwfdecAudioFormat, char **);
+} audio_codecs[] = {
+ { "builtin", swfdec_audio_decoder_builtin_new, swfdec_audio_decoder_builtin_prepare },
+#ifdef HAVE_GST
+ { "gst", swfdec_audio_decoder_gst_new, swfdec_audio_decoder_gst_prepare },
+#endif
+};
+
+gboolean
+swfdec_audio_decoder_prepare (guint codec, SwfdecAudioFormat format, char **missing)
+{
+ char *detail = NULL, *s = NULL;
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (audio_codecs); i++) {
+ if (audio_codecs[i].prepare (codec, format, &s)) {
+ g_free (detail);
+ g_free (s);
+ if (missing)
+ *missing = NULL;
+ return TRUE;
+ }
+ if (s) {
+ if (detail == NULL)
+ detail = s;
+ else
+ g_free (s);
+ s = NULL;
+ }
+ }
+ if (missing)
+ *missing = detail;
+ return FALSE;
+}
+
+/**
+ * swfdec_audio_decoder_new:
+ * @format: #SwfdecAudioCodec 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 (guint codec, SwfdecAudioFormat format)
+{
+ SwfdecAudioDecoder *ret;
+ guint i;
+
+ g_return_val_if_fail (SWFDEC_IS_AUDIO_FORMAT (format), NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (audio_codecs); i++) {
+ ret = audio_codecs[i].func (codec, format);
+ if (ret)
+ break;
+ }
+
+ if (ret == NULL) {
+ ret = g_object_new (SWFDEC_TYPE_AUDIO_DECODER, NULL);
+ swfdec_audio_decoder_error (ret, "no suitable decoder for audio codec %u", codec);
+ }
+
+ ret->codec = codec;
+ ret->format = format;
+
+ return ret;
+}
+
+/**
+ * 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)
+{
+ SwfdecAudioDecoderClass *klass;
+
+ g_return_if_fail (SWFDEC_IS_AUDIO_DECODER (decoder));
+
+ if (decoder->error)
+ return;
+ klass = SWFDEC_AUDIO_DECODER_GET_CLASS (decoder);
+ klass->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)
+{
+ SwfdecAudioDecoderClass *klass;
+
+ g_return_val_if_fail (SWFDEC_IS_AUDIO_DECODER (decoder), NULL);
+
+ if (decoder->error)
+ return NULL;
+ klass = SWFDEC_AUDIO_DECODER_GET_CLASS (decoder);
+ return klass->pull (decoder);
+}
+
+void
+swfdec_audio_decoder_error (SwfdecAudioDecoder *decoder, const char *error, ...)
+{
+ va_list args;
+
+ g_return_if_fail (SWFDEC_IS_AUDIO_DECODER (decoder));
+ g_return_if_fail (error != NULL);
+
+ va_start (args, error);
+ swfdec_audio_decoder_errorv (decoder, error, args);
+ va_end (args);
+}
+
+void
+swfdec_audio_decoder_errorv (SwfdecAudioDecoder *decoder, const char *error, va_list args)
+{
+ char *real;
+
+ g_return_if_fail (SWFDEC_IS_AUDIO_DECODER (decoder));
+ g_return_if_fail (error != NULL);
+
+ real = g_strdup_vprintf (error, args);
+ SWFDEC_ERROR ("error decoding audio: %s", real);
+ g_free (real);
+ decoder->error = TRUE;
+}
+
diff --git a/swfdec/swfdec_audio_decoder.h b/swfdec/swfdec_audio_decoder.h
new file mode 100644
index 0000000..6d58303
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder.h
@@ -0,0 +1,89 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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_AUDIO_DECODER_H_
+#define _SWFDEC_AUDIO_DECODER_H_
+
+#include <swfdec/swfdec_buffer.h>
+#include <swfdec/swfdec_audio_internal.h>
+
+G_BEGIN_DECLS
+
+
+#define SWFDEC_AUDIO_CODEC_UNDEFINED 0
+#define SWFDEC_AUDIO_CODEC_ADPCM 1
+#define SWFDEC_AUDIO_CODEC_MP3 2
+#define SWFDEC_AUDIO_CODEC_UNCOMPRESSED 3
+#define SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ 5
+#define SWFDEC_AUDIO_CODEC_NELLYMOSER 6
+
+
+typedef struct _SwfdecAudioDecoder SwfdecAudioDecoder;
+typedef struct _SwfdecAudioDecoderClass SwfdecAudioDecoderClass;
+
+#define SWFDEC_TYPE_AUDIO_DECODER (swfdec_audio_decoder_get_type())
+#define SWFDEC_IS_AUDIO_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AUDIO_DECODER))
+#define SWFDEC_IS_AUDIO_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AUDIO_DECODER))
+#define SWFDEC_AUDIO_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AUDIO_DECODER, SwfdecAudioDecoder))
+#define SWFDEC_AUDIO_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AUDIO_DECODER, SwfdecAudioDecoderClass))
+#define SWFDEC_AUDIO_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AUDIO_DECODER, SwfdecAudioDecoderClass))
+
+struct _SwfdecAudioDecoder
+{
+ GObject object;
+
+ /*< private >*/
+ guint codec; /* codec this decoder uses */
+ SwfdecAudioFormat format; /* format the codec was initialized with */
+ gboolean error; /* if this codec is in an error state */
+};
+
+struct _SwfdecAudioDecoderClass
+{
+ GObjectClass object_class;
+
+ void (* push) (SwfdecAudioDecoder * decoder,
+ SwfdecBuffer * buffer);
+ SwfdecBuffer * (* pull) (SwfdecAudioDecoder * decoder);
+};
+
+GType swfdec_audio_decoder_get_type (void);
+
+gboolean swfdec_audio_decoder_prepare (guint codec,
+ SwfdecAudioFormat format,
+ char ** missing);
+SwfdecAudioDecoder * swfdec_audio_decoder_new (guint codec,
+ SwfdecAudioFormat format);
+
+void swfdec_audio_decoder_push (SwfdecAudioDecoder * decoder,
+ SwfdecBuffer * buffer);
+SwfdecBuffer * swfdec_audio_decoder_pull (SwfdecAudioDecoder * decoder);
+
+/* for subclasses */
+void swfdec_audio_decoder_error (SwfdecAudioDecoder * decoder,
+ const char * error,
+ ...) G_GNUC_PRINTF (2, 3);
+void swfdec_audio_decoder_errorv (SwfdecAudioDecoder * decoder,
+ const char * error,
+ va_list args);
+
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_audio_decoder_adpcm.c b/swfdec/swfdec_audio_decoder_adpcm.c
new file mode 100644
index 0000000..bbaf222
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder_adpcm.c
@@ -0,0 +1,199 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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_audio_decoder_adpcm.h"
+#include "swfdec_debug.h"
+#include "swfdec_internal.h"
+
+G_DEFINE_TYPE (SwfdecAudioDecoderAdpcm, swfdec_audio_decoder_adpcm, SWFDEC_TYPE_AUDIO_DECODER)
+
+static const int indexTable[4][16] = {
+ { -1, 2 },
+ { -1, -1, 2, 4 },
+ { -1, -1, -1, -1, 2, 4, 6, 8 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 }
+};
+
+static const int stepSizeTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+static SwfdecBuffer *
+swfdec_audio_decoder_adpcm_decode_chunk (SwfdecBits *bits, guint n_bits,
+ guint channels, guint granularity)
+{
+ SwfdecBuffer *ret;
+ guint len, repeat;
+ guint i, j, ch;
+ guint index[2];
+ int pred[2];
+ gint16 *out;
+ guint delta, sign, sign_mask;
+ int diff;
+ const int *realIndexTable;
+ guint step[2];
+
+ /* for scaling up the audio to 44100kHz */
+ repeat = 2 * granularity - channels;
+
+ realIndexTable = indexTable[n_bits - 2];
+ for (ch = 0; ch < channels; ch++) {
+ /* can't use get_s16 here since that would be aligned */
+ pred[ch] = swfdec_bits_getsbits (bits, 16);
+ index[ch] = swfdec_bits_getbits (bits, 6);
+ if (index[ch] >= G_N_ELEMENTS (stepSizeTable)) {
+ SWFDEC_ERROR ("initial index too big: %u, max allowed is %td",
+ index[ch], G_N_ELEMENTS (stepSizeTable) - 1);
+ index[ch] = G_N_ELEMENTS (stepSizeTable) - 1;
+ }
+ step[ch] = stepSizeTable[index[ch]];
+ }
+ len = swfdec_bits_left (bits) / channels / n_bits;
+ len = MIN (len, 4095);
+ ret = swfdec_buffer_new ((len + 1) * sizeof (gint16) * granularity * 2);
+ out = (gint16 *) (void *) ret->data;
+ /* output initial value */
+ SWFDEC_LOG ("decoding %u samples", len + 1);
+ for (ch = 0; ch < channels; ch++)
+ *out++ = pred[ch];
+ /* upscale to 44.1kHz */
+ for (ch = 0; ch < repeat; ch++) {
+ *out = out[-(gssize) channels];
+ out++;
+ }
+
+ sign_mask = 1 << (n_bits - 1);
+ for (i = 0; i < len; i++) {
+ for (ch = 0; ch < channels; ch++) {
+ /* Step 1 - get the delta value */
+ delta = swfdec_bits_getbits (bits, n_bits);
+
+ /* Step 2 - Separate sign and magnitude */
+ sign = delta & sign_mask;
+ delta -= sign;
+
+ /* Step 3 - Find new index value (for later) */
+ index[ch] += realIndexTable[delta];
+ if ( index[ch] >= G_MAXINT ) index[ch] = 0; /* underflow */
+ if ( index[ch] >= G_N_ELEMENTS (stepSizeTable) ) index[ch] = G_N_ELEMENTS (stepSizeTable) - 1;
+
+ /* Step 4 - Compute difference and new predicted value */
+ j = n_bits - 1;
+ diff = step[ch] >> j;
+ do {
+ j--;
+ if (delta & 1)
+ diff += step[ch] >> j;
+ delta >>= 1;
+ } while (j > 0 && delta);
+
+ if ( sign )
+ pred[ch] -= diff;
+ else
+ pred[ch] += diff;
+
+ /* Step 5 - clamp output value */
+ pred[ch] = CLAMP (pred[ch], -32768, 32767);
+
+ /* Step 6 - Update step value */
+ step[ch] = stepSizeTable[index[ch]];
+
+ /* Step 7 - Output value */
+ *out++ = pred[ch];
+ }
+
+ /* upscale to 44.1kHz */
+ for (ch = 0; ch < repeat; ch++) {
+ *out = out[-(gssize) channels];
+ out++;
+ }
+ }
+ return ret;
+}
+
+static void
+swfdec_audio_decoder_adpcm_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
+{
+ SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
+ guint channels, n_bits, granularity;
+ SwfdecBits bits;
+
+ if (buffer == NULL)
+ return;
+
+ channels = swfdec_audio_format_get_channels (dec->format);
+ granularity = swfdec_audio_format_get_granularity (dec->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_audio_decoder_adpcm_decode_chunk (&bits, n_bits, channels, granularity);
+ if (buffer)
+ swfdec_buffer_queue_push (adpcm->queue, buffer);
+ }
+}
+
+static SwfdecBuffer *
+swfdec_audio_decoder_adpcm_pull (SwfdecAudioDecoder *dec)
+{
+ SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
+
+ return swfdec_buffer_queue_pull_buffer (adpcm->queue);
+}
+
+static void
+swfdec_audio_decoder_adpcm_dispose (GObject *object)
+{
+ SwfdecAudioDecoderAdpcm *dec = (SwfdecAudioDecoderAdpcm *) object;
+
+ swfdec_buffer_queue_unref (dec->queue);
+
+ G_OBJECT_CLASS (swfdec_audio_decoder_adpcm_parent_class)->dispose (object);
+}
+
+static void
+swfdec_audio_decoder_adpcm_class_init (SwfdecAudioDecoderAdpcmClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SwfdecAudioDecoderClass *decoder_class = SWFDEC_AUDIO_DECODER_CLASS (klass);
+
+ object_class->dispose = swfdec_audio_decoder_adpcm_dispose;
+
+ decoder_class->pull = swfdec_audio_decoder_adpcm_pull;
+ decoder_class->push = swfdec_audio_decoder_adpcm_push;
+}
+
+static void
+swfdec_audio_decoder_adpcm_init (SwfdecAudioDecoderAdpcm *audio_decoder_adpcm)
+{
+}
+
diff --git a/swfdec/swfdec_audio_decoder_adpcm.h b/swfdec/swfdec_audio_decoder_adpcm.h
new file mode 100644
index 0000000..9367bb7
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder_adpcm.h
@@ -0,0 +1,54 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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_AUDIO_DECODER_ADPCM_H_
+#define _SWFDEC_AUDIO_DECODER_ADPCM_H_
+
+#include <swfdec/swfdec_audio_decoder.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecAudioDecoderAdpcm SwfdecAudioDecoderAdpcm;
+typedef struct _SwfdecAudioDecoderAdpcmClass SwfdecAudioDecoderAdpcmClass;
+
+#define SWFDEC_TYPE_AUDIO_DECODER_ADPCM (swfdec_audio_decoder_adpcm_get_type())
+#define SWFDEC_IS_AUDIO_DECODER_ADPCM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AUDIO_DECODER_ADPCM))
+#define SWFDEC_IS_AUDIO_DECODER_ADPCM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AUDIO_DECODER_ADPCM))
+#define SWFDEC_AUDIO_DECODER_ADPCM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AUDIO_DECODER_ADPCM, SwfdecAudioDecoderAdpcm))
+#define SWFDEC_AUDIO_DECODER_ADPCM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AUDIO_DECODER_ADPCM, SwfdecAudioDecoderAdpcmClass))
+#define SWFDEC_AUDIO_DECODER_ADPCM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AUDIO_DECODER_ADPCM, SwfdecAudioDecoderAdpcmClass))
+
+struct _SwfdecAudioDecoderAdpcm
+{
+ SwfdecAudioDecoder decoder;
+
+ SwfdecBufferQueue * queue; /* queue collecting output buffers */
+};
+
+struct _SwfdecAudioDecoderAdpcmClass
+{
+ SwfdecAudioDecoderClass decoder_class;
+};
+
+GType swfdec_audio_decoder_adpcm_get_type (void);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_audio_decoder_gst.c b/swfdec/swfdec_audio_decoder_gst.c
new file mode 100644
index 0000000..45cbc90
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder_gst.c
@@ -0,0 +1,200 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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 <gst/pbutils/pbutils.h>
+
+#include "swfdec_audio_decoder_gst.h"
+#include "swfdec_debug.h"
+#include "swfdec_internal.h"
+
+/*** CAPS MATCHING ***/
+
+static GstCaps *
+swfdec_audio_decoder_get_caps (guint codec, SwfdecAudioFormat format)
+{
+ GstCaps *caps;
+ char *s;
+
+ switch (codec) {
+ case SWFDEC_AUDIO_CODEC_MP3:
+ s = g_strdup ("audio/mpeg, mpegversion=(int)1, layer=(int)3");
+ break;
+ case SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ:
+ s = g_strdup ("audio/x-nellymoser, rate=8000, channels=1");
+ break;
+ case SWFDEC_AUDIO_CODEC_NELLYMOSER:
+ s = g_strdup_printf ("audio/x-nellymoser, rate=%d, channels=%d",
+ swfdec_audio_format_get_rate (format),
+ swfdec_audio_format_get_channels (format));
+ break;
+ default:
+ return NULL;
+ }
+
+ caps = gst_caps_from_string (s);
+ g_assert (caps);
+ g_free (s);
+ return caps;
+}
+
+G_DEFINE_TYPE (SwfdecAudioDecoderGst, swfdec_audio_decoder_gst, SWFDEC_TYPE_AUDIO_DECODER)
+
+static void
+swfdec_audio_decoder_gst_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
+{
+ SwfdecAudioDecoderGst *player = SWFDEC_AUDIO_DECODER_GST (dec);
+ GstBuffer *buf;
+
+ if (buffer == NULL) {
+ swfdec_gst_decoder_push_eos (&player->dec);
+ } else {
+ swfdec_buffer_ref (buffer);
+ buf = swfdec_gst_buffer_new (buffer);
+ if (!swfdec_gst_decoder_push (&player->dec, buf))
+ goto error;
+ }
+ while ((buf = swfdec_gst_decoder_pull (&player->dec))) {
+ if (!swfdec_gst_decoder_push (&player->convert, buf))
+ goto error;
+ }
+ while ((buf = swfdec_gst_decoder_pull (&player->convert))) {
+ if (!swfdec_gst_decoder_push (&player->resample, buf))
+ goto error;
+ }
+ return;
+
+error:
+ swfdec_audio_decoder_error (dec, "error pushing");
+}
+
+static SwfdecBuffer *
+swfdec_audio_decoder_gst_pull (SwfdecAudioDecoder *dec)
+{
+ SwfdecAudioDecoderGst *player = SWFDEC_AUDIO_DECODER_GST (dec);
+ GstBuffer *buf;
+
+ buf = swfdec_gst_decoder_pull (&player->resample);
+ if (buf == NULL)
+ return NULL;
+ return swfdec_buffer_new_from_gst (buf);
+}
+
+static void
+swfdec_audio_decoder_gst_dispose (GObject *object)
+{
+ SwfdecAudioDecoderGst *player = (SwfdecAudioDecoderGst *) object;
+
+ swfdec_gst_decoder_finish (&player->dec);
+ swfdec_gst_decoder_finish (&player->convert);
+ swfdec_gst_decoder_finish (&player->resample);
+
+ G_OBJECT_CLASS (swfdec_audio_decoder_gst_parent_class)->dispose (object);
+}
+
+static void
+swfdec_audio_decoder_gst_class_init (SwfdecAudioDecoderGstClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SwfdecAudioDecoderClass *decoder_class = SWFDEC_AUDIO_DECODER_CLASS (klass);
+
+ object_class->dispose = swfdec_audio_decoder_gst_dispose;
+
+ decoder_class->pull = swfdec_audio_decoder_gst_pull;
+ decoder_class->push = swfdec_audio_decoder_gst_push;
+}
+
+static void
+swfdec_audio_decoder_gst_init (SwfdecAudioDecoderGst *audio_decoder_gst)
+{
+}
+
+SwfdecAudioDecoder *
+swfdec_audio_decoder_gst_new (guint type, SwfdecAudioFormat format)
+{
+ SwfdecAudioDecoderGst *player;
+ GstCaps *srccaps, *sinkcaps;
+
+ srccaps = swfdec_audio_decoder_get_caps (type, format);
+ if (srccaps == NULL)
+ return NULL;
+
+ player = g_object_new (SWFDEC_TYPE_AUDIO_DECODER_GST, NULL);
+
+ /* create decoder */
+ sinkcaps = gst_caps_from_string ("audio/x-raw-int");
+ g_assert (sinkcaps);
+ if (!swfdec_gst_decoder_init (&player->dec, NULL, srccaps, sinkcaps))
+ goto error;
+ /* create audioconvert */
+ gst_caps_unref (srccaps);
+ srccaps = sinkcaps;
+ sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, channels=2");
+ g_assert (sinkcaps);
+ if (!swfdec_gst_decoder_init (&player->convert, "audioconvert", srccaps, sinkcaps))
+ goto error;
+ /* create audiorate */
+ gst_caps_unref (srccaps);
+ srccaps = sinkcaps;
+ sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, rate=44100, channels=2");
+ g_assert (sinkcaps);
+ if (!swfdec_gst_decoder_init (&player->resample, "audioresample", srccaps, sinkcaps))
+ goto error;
+ g_object_set_data (G_OBJECT (player->resample.sink), "swfdec-player", player);
+
+ gst_caps_unref (srccaps);
+ gst_caps_unref (sinkcaps);
+ return SWFDEC_AUDIO_DECODER (player);
+
+error:
+ g_object_unref (player);
+ gst_caps_unref (srccaps);
+ gst_caps_unref (sinkcaps);
+ return NULL;
+}
+
+/*** MISSING PLUGIN SUPPORT ***/
+
+gboolean
+swfdec_audio_decoder_gst_prepare (guint codec, SwfdecAudioFormat format, char **detail)
+{
+ GstElementFactory *factory;
+ GstCaps *caps;
+
+ /* Check if we can handle the format at all. If not, no plugin will help us. */
+ caps = swfdec_audio_decoder_get_caps (codec, format);
+ if (caps == NULL)
+ return FALSE;
+
+ /* If we can already handle it, woohoo! */
+ factory = swfdec_gst_get_element_factory (caps);
+ if (factory != NULL) {
+ gst_object_unref (factory);
+ return TRUE;
+ }
+
+ /* need to install plugins... */
+ *detail = gst_missing_decoder_installer_detail_new (caps);
+ gst_caps_unref (caps);
+ return FALSE;
+}
+
diff --git a/swfdec/swfdec_audio_decoder_gst.h b/swfdec/swfdec_audio_decoder_gst.h
new file mode 100644
index 0000000..284eb0c
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder_gst.h
@@ -0,0 +1,63 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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_AUDIO_DECODER_GST_H_
+#define _SWFDEC_AUDIO_DECODER_GST_H_
+
+#include <swfdec/swfdec_audio_decoder.h>
+#include <swfdec/swfdec_codec_gst.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecAudioDecoderGst SwfdecAudioDecoderGst;
+typedef struct _SwfdecAudioDecoderGstClass SwfdecAudioDecoderGstClass;
+
+#define SWFDEC_TYPE_AUDIO_DECODER_GST (swfdec_audio_decoder_gst_get_type())
+#define SWFDEC_IS_AUDIO_DECODER_GST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AUDIO_DECODER_GST))
+#define SWFDEC_IS_AUDIO_DECODER_GST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AUDIO_DECODER_GST))
+#define SWFDEC_AUDIO_DECODER_GST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AUDIO_DECODER_GST, SwfdecAudioDecoderGst))
+#define SWFDEC_AUDIO_DECODER_GST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AUDIO_DECODER_GST, SwfdecAudioDecoderGstClass))
+#define SWFDEC_AUDIO_DECODER_GST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AUDIO_DECODER_GST, SwfdecAudioDecoderGstClass))
+
+struct _SwfdecAudioDecoderGst
+{
+ SwfdecAudioDecoder decoder;
+
+ SwfdecGstDecoder dec; /* the actual decoder */
+ SwfdecGstDecoder convert; /* audioconvert element to got to S16 stereo */
+ SwfdecGstDecoder resample; /* resampler to 44100Hz */
+};
+
+struct _SwfdecAudioDecoderGstClass
+{
+ SwfdecAudioDecoderClass decoder_class;
+};
+
+GType swfdec_audio_decoder_gst_get_type (void);
+
+SwfdecAudioDecoder * swfdec_audio_decoder_gst_new (guint codec,
+ SwfdecAudioFormat format);
+gboolean swfdec_audio_decoder_gst_prepare (guint codec,
+ SwfdecAudioFormat format,
+ char ** missing);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_audio_decoder_uncompressed.c b/swfdec/swfdec_audio_decoder_uncompressed.c
new file mode 100644
index 0000000..edd8f8e
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder_uncompressed.c
@@ -0,0 +1,145 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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_audio_decoder_uncompressed.h"
+#include "swfdec_debug.h"
+#include "swfdec_internal.h"
+
+G_DEFINE_TYPE (SwfdecAudioDecoderUncompressed, swfdec_audio_decoder_uncompressed, SWFDEC_TYPE_AUDIO_DECODER)
+
+static SwfdecBuffer *
+swfdec_audio_decoder_uncompressed_upscale (SwfdecBuffer *buffer, SwfdecAudioFormat format)
+{
+ guint channels = swfdec_audio_format_get_channels (format);
+ guint granularity = swfdec_audio_format_get_granularity (format);
+ SwfdecBuffer *ret;
+ guint i, j;
+ gint16 *src, *dest;
+
+ ret = swfdec_buffer_new (buffer->length * 2 / channels * granularity);
+ src = (gint16 *) buffer->data;
+ dest = (gint16 *) ret->data;
+ for (i = 0; i < buffer->length / 2; i++) {
+ for (j = 0; j < granularity; j++) {
+ *dest++ = src[0];
+ *dest++ = src[channels - 1];
+ }
+ src += channels;
+ }
+
+ swfdec_buffer_unref (buffer);
+ return ret;
+}
+
+static SwfdecBuffer *
+swfdec_audio_decoder_uncompressed_decode_8bit (SwfdecBuffer *buffer)
+{
+ SwfdecBuffer *ret;
+ gint16 *out;
+ guint8 *in;
+ guint i;
+
+ ret = swfdec_buffer_new (buffer->length * 2);
+ out = (gint16 *) (void *) ret->data;
+ in = buffer->data;
+ for (i = 0; i < buffer->length; i++) {
+ *out = ((gint16) *in << 8) ^ (-1);
+ out++;
+ in++;
+ }
+ return ret;
+}
+
+static SwfdecBuffer *
+swfdec_audio_decoder_uncompressed_decode_16bit (SwfdecBuffer *buffer)
+{
+ SwfdecBuffer *ret;
+ gint16 *src, *dest;
+ guint i;
+
+ ret = swfdec_buffer_new (buffer->length);
+ src = (gint16 *) buffer->data;
+ dest = (gint16 *) ret->data;
+ for (i = 0; i < buffer->length; i += 2) {
+ *dest = GINT16_FROM_LE (*src);
+ dest++;
+ src++;
+ }
+
+ return ret;
+}
+
+static void
+swfdec_audio_decoder_uncompressed_push (SwfdecAudioDecoder *decoder,
+ SwfdecBuffer *buffer)
+{
+ SwfdecBuffer *tmp;
+
+ if (buffer == NULL)
+ return;
+
+ if (swfdec_audio_format_is_16bit (decoder->format))
+ tmp = swfdec_audio_decoder_uncompressed_decode_16bit (buffer);
+ else
+ tmp = swfdec_audio_decoder_uncompressed_decode_8bit (buffer);
+
+ tmp = swfdec_audio_decoder_uncompressed_upscale (tmp, decoder->format);
+ swfdec_buffer_queue_push (SWFDEC_AUDIO_DECODER_UNCOMPRESSED (decoder)->queue,
+ tmp);
+}
+
+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_dispose (GObject *object)
+{
+ SwfdecAudioDecoderUncompressed *dec = (SwfdecAudioDecoderUncompressed *) object;
+
+ swfdec_buffer_queue_unref (dec->queue);
+
+ G_OBJECT_CLASS (swfdec_audio_decoder_uncompressed_parent_class)->dispose (object);
+}
+
+static void
+swfdec_audio_decoder_uncompressed_class_init (SwfdecAudioDecoderUncompressedClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ SwfdecAudioDecoderClass *decoder_class = SWFDEC_AUDIO_DECODER_CLASS (klass);
+
+ object_class->dispose = swfdec_audio_decoder_uncompressed_dispose;
+
+ decoder_class->pull = swfdec_audio_decoder_uncompressed_pull;
+ decoder_class->push = swfdec_audio_decoder_uncompressed_push;
+}
+
+static void
+swfdec_audio_decoder_uncompressed_init (SwfdecAudioDecoderUncompressed *audio_decoder_uncompressed)
+{
+}
+
diff --git a/swfdec/swfdec_audio_decoder_uncompressed.h b/swfdec/swfdec_audio_decoder_uncompressed.h
new file mode 100644
index 0000000..64bf8b8
--- /dev/null
+++ b/swfdec/swfdec_audio_decoder_uncompressed.h
@@ -0,0 +1,54 @@
+/* Swfdec
+ * Copyright (C) 2006-2008 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_AUDIO_DECODER_UNCOMPRESSED_H_
+#define _SWFDEC_AUDIO_DECODER_UNCOMPRESSED_H_
+
+#include <swfdec/swfdec_audio_decoder.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecAudioDecoderUncompressed SwfdecAudioDecoderUncompressed;
+typedef struct _SwfdecAudioDecoderUncompressedClass SwfdecAudioDecoderUncompressedClass;
+
+#define SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED (swfdec_audio_decoder_uncompressed_get_type())
+#define SWFDEC_IS_AUDIO_DECODER_UNCOMPRESSED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED))
+#define SWFDEC_IS_AUDIO_DECODER_UNCOMPRESSED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED))
+#define SWFDEC_AUDIO_DECODER_UNCOMPRESSED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED, SwfdecAudioDecoderUncompressed))
+#define SWFDEC_AUDIO_DECODER_UNCOMPRESSED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED, SwfdecAudioDecoderUncompressedClass))
+#define SWFDEC_AUDIO_DECODER_UNCOMPRESSED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AUDIO_DECODER_UNCOMPRESSED, SwfdecAudioDecoderUncompressedClass))
+
+struct _SwfdecAudioDecoderUncompressed
+{
+ SwfdecAudioDecoder decoder;
+
+ SwfdecBufferQueue * queue; /* queue collecting output buffers */
+};
+
+struct _SwfdecAudioDecoderUncompressedClass
+{
+ SwfdecAudioDecoderClass decoder_class;
+};
+
+GType swfdec_audio_decoder_uncompressed_get_type (void);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_audio_flv.c b/swfdec/swfdec_audio_flv.c
index b060d74..df00208 100644
--- a/swfdec/swfdec_audio_flv.c
+++ b/swfdec/swfdec_audio_flv.c
@@ -35,7 +35,7 @@ swfdec_audio_flv_dispose (GObject *object)
SwfdecAudioFlv *flv = SWFDEC_AUDIO_FLV (object);
if (flv->decoder != NULL) {
- swfdec_audio_decoder_free (flv->decoder);
+ g_object_unref (flv->decoder);
flv->decoder = NULL;
}
g_queue_foreach (flv->playback_queue, (GFunc) swfdec_buffer_unref, NULL);
@@ -87,7 +87,7 @@ swfdec_audio_flv_decode_one (SwfdecAudioFlv *flv)
if (flv->in == 0) {
/* init */
if (flv->decoder) {
- swfdec_audio_decoder_free (flv->decoder);
+ g_object_unref (flv->decoder);
flv->decoder = NULL;
}
flv->format = format;
diff --git a/swfdec/swfdec_audio_flv.h b/swfdec/swfdec_audio_flv.h
index 91671f7..9ee2ca3 100644
--- a/swfdec/swfdec_audio_flv.h
+++ b/swfdec/swfdec_audio_flv.h
@@ -20,6 +20,7 @@
#ifndef _SWFDEC_AUDIO_FLV_H_
#define _SWFDEC_AUDIO_FLV_H_
+#include <swfdec/swfdec_audio_decoder.h>
#include <swfdec/swfdec_audio_internal.h>
#include <swfdec/swfdec_flv_decoder.h>
diff --git a/swfdec/swfdec_audio_stream.c b/swfdec/swfdec_audio_stream.c
index ad7dd60..3c73ad1 100644
--- a/swfdec/swfdec_audio_stream.c
+++ b/swfdec/swfdec_audio_stream.c
@@ -38,7 +38,7 @@ swfdec_audio_stream_dispose (GObject *object)
SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (object);
if (stream->decoder != NULL) {
- swfdec_audio_decoder_free (stream->decoder);
+ g_object_unref (stream->decoder);
stream->decoder = NULL;
}
g_queue_foreach (stream->playback_queue, (GFunc) swfdec_buffer_unref, NULL);
diff --git a/swfdec/swfdec_audio_stream.h b/swfdec/swfdec_audio_stream.h
index 5d7c531..7959653 100644
--- a/swfdec/swfdec_audio_stream.h
+++ b/swfdec/swfdec_audio_stream.h
@@ -22,8 +22,8 @@
#ifndef _SWFDEC_AUDIO_STREAM_H_
#define _SWFDEC_AUDIO_STREAM_H_
+#include <swfdec/swfdec_audio_decoder.h>
#include <swfdec/swfdec_audio_internal.h>
-#include <swfdec/swfdec_codec_audio.h>
G_BEGIN_DECLS
diff --git a/swfdec/swfdec_codec_adpcm.c b/swfdec/swfdec_codec_adpcm.c
deleted file mode 100644
index bdd14f8..0000000
--- a/swfdec/swfdec_codec_adpcm.c
+++ /dev/null
@@ -1,203 +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_audio.h"
-#include "swfdec_bits.h"
-#include "swfdec_debug.h"
-#include "swfdec_internal.h"
-
-typedef struct {
- SwfdecAudioDecoder decoder;
- SwfdecAudioFormat format;
- SwfdecBufferQueue * queue;
-} SwfdecAudioDecoderAdpcm;
-
-static const int indexTable[4][16] = {
- { -1, 2 },
- { -1, -1, 2, 4 },
- { -1, -1, -1, -1, 2, 4, 6, 8 },
- { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 }
-};
-
-static const int stepSizeTable[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
-};
-
-static SwfdecBuffer *
-swfdec_audio_decoder_adpcm_decode_chunk (SwfdecBits *bits, guint n_bits,
- guint channels, guint granularity)
-{
- SwfdecBuffer *ret;
- guint len, repeat;
- guint i, j, ch;
- guint index[2];
- int pred[2];
- gint16 *out;
- guint delta, sign, sign_mask;
- int diff;
- const int *realIndexTable;
- guint step[2];
-
- /* for scaling up the audio to 44100kHz */
- repeat = 2 * granularity - channels;
-
- realIndexTable = indexTable[n_bits - 2];
- for (ch = 0; ch < channels; ch++) {
- /* can't use get_s16 here since that would be aligned */
- pred[ch] = swfdec_bits_getsbits (bits, 16);
- index[ch] = swfdec_bits_getbits (bits, 6);
- if (index[ch] >= G_N_ELEMENTS (stepSizeTable)) {
- SWFDEC_ERROR ("initial index too big: %u, max allowed is %td",
- index[ch], G_N_ELEMENTS (stepSizeTable) - 1);
- index[ch] = G_N_ELEMENTS (stepSizeTable) - 1;
- }
- step[ch] = stepSizeTable[index[ch]];
- }
- len = swfdec_bits_left (bits) / channels / n_bits;
- len = MIN (len, 4095);
- ret = swfdec_buffer_new ((len + 1) * sizeof (gint16) * granularity * 2);
- out = (gint16 *) (void *) ret->data;
- /* output initial value */
- SWFDEC_LOG ("decoding %u samples", len + 1);
- for (ch = 0; ch < channels; ch++)
- *out++ = pred[ch];
- /* upscale to 44.1kHz */
- for (ch = 0; ch < repeat; ch++) {
- *out = out[-(gssize) channels];
- out++;
- }
-
- sign_mask = 1 << (n_bits - 1);
- for (i = 0; i < len; i++) {
- for (ch = 0; ch < channels; ch++) {
- /* Step 1 - get the delta value */
- delta = swfdec_bits_getbits (bits, n_bits);
-
- /* Step 2 - Separate sign and magnitude */
- sign = delta & sign_mask;
- delta -= sign;
-
- /* Step 3 - Find new index value (for later) */
- index[ch] += realIndexTable[delta];
- if ( index[ch] >= G_MAXINT ) index[ch] = 0; /* underflow */
- if ( index[ch] >= G_N_ELEMENTS (stepSizeTable) ) index[ch] = G_N_ELEMENTS (stepSizeTable) - 1;
-
- /* Step 4 - Compute difference and new predicted value */
- j = n_bits - 1;
- diff = step[ch] >> j;
- do {
- j--;
- if (delta & 1)
- diff += step[ch] >> j;
- delta >>= 1;
- } while (j > 0 && delta);
-
- if ( sign )
- pred[ch] -= diff;
- else
- pred[ch] += diff;
-
- /* Step 5 - clamp output value */
- pred[ch] = CLAMP (pred[ch], -32768, 32767);
-
- /* Step 6 - Update step value */
- step[ch] = stepSizeTable[index[ch]];
-
- /* Step 7 - Output value */
- *out++ = pred[ch];
- }
-
- /* upscale to 44.1kHz */
- for (ch = 0; ch < repeat; ch++) {
- *out = out[-(gssize) channels];
- out++;
- }
- }
- return ret;
-}
-
-static void
-swfdec_audio_decoder_adpcm_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
-{
- SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
- guint channels, n_bits, granularity;
- SwfdecBits bits;
-
- if (buffer == NULL)
- return;
-
- channels = swfdec_audio_format_get_channels (adpcm->format);
- granularity = swfdec_audio_format_get_granularity (adpcm->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_audio_decoder_adpcm_decode_chunk (&bits, n_bits, channels, granularity);
- if (buffer)
- swfdec_buffer_queue_push (adpcm->queue, buffer);
- }
-}
-
-static SwfdecBuffer *
-swfdec_audio_decoder_adpcm_pull (SwfdecAudioDecoder *dec)
-{
- SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
-
- return swfdec_buffer_queue_pull_buffer (adpcm->queue);
-}
-
-static void
-swfdec_audio_decoder_adpcm_free (SwfdecAudioDecoder *dec)
-{
- SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
-
- swfdec_buffer_queue_unref (adpcm->queue);
- g_slice_free (SwfdecAudioDecoderAdpcm, adpcm);
-}
-
-SwfdecAudioDecoder *
-swfdec_audio_decoder_adpcm_new (guint type, SwfdecAudioFormat format)
-{
- SwfdecAudioDecoderAdpcm *adpcm;
-
- if (type != SWFDEC_AUDIO_CODEC_ADPCM)
- return NULL;
- adpcm = g_slice_new (SwfdecAudioDecoderAdpcm);
- adpcm->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 ();
-
- return &adpcm->decoder;
-}
-
diff --git a/swfdec/swfdec_codec_audio.c b/swfdec/swfdec_codec_audio.c
deleted file mode 100644
index e4d7b3b..0000000
--- a/swfdec/swfdec_codec_audio.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/* 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"
-#include "swfdec_internal.h"
-
-/*** UNCOMPRESSED SOUND ***/
-
-typedef struct {
- SwfdecAudioDecoder decoder;
- SwfdecAudioFormat format;
- SwfdecBufferQueue * queue; /* queue collecting output buffers */
-} SwfdecAudioDecoderUncompressed;
-
-static void
-swfdec_audio_decoder_uncompressed_upscale (SwfdecAudioDecoder *decoder,
- SwfdecBuffer *buffer)
-{
- SwfdecAudioDecoderUncompressed *unc = (SwfdecAudioDecoderUncompressed *) decoder;
- guint channels = swfdec_audio_format_get_channels (unc->format);
- guint granularity = swfdec_audio_format_get_granularity (unc->format);
- SwfdecBuffer *ret;
- guint i, j;
- gint16 *src, *dest;
-
- ret = swfdec_buffer_new (buffer->length * 2 / channels * granularity);
- src = (gint16 *) buffer->data;
- dest = (gint16 *) ret->data;
- for (i = 0; i < buffer->length / 2; i++) {
- for (j = 0; j < granularity; j++) {
- *dest++ = src[0];
- *dest++ = src[channels - 1];
- }
- src += channels;
- }
-
- swfdec_buffer_queue_push (unc->queue, ret);
-}
-
-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 (buffer->length * 2);
- out = (gint16 *) (void *) ret->data;
- in = buffer->data;
- for (i = 0; i < buffer->length; i++) {
- *out = ((gint16) *in << 8) ^ (-1);
- out++;
- in++;
- }
- swfdec_audio_decoder_uncompressed_upscale (decoder, ret);
- swfdec_buffer_unref (ret);
-}
-
-static void
-swfdec_audio_decoder_uncompressed_decode_16bit (SwfdecAudioDecoder *decoder,
- SwfdecBuffer *buffer)
-{
- SwfdecBuffer *tmp;
- gint16 *src, *dest;
- guint i;
-
- if (buffer == NULL)
- return;
-
- tmp = swfdec_buffer_new (buffer->length);
- src = (gint16 *) buffer->data;
- dest = (gint16 *) tmp->data;
- for (i = 0; i < buffer->length; i += 2) {
- *dest = GINT16_FROM_LE (*src);
- dest++;
- src++;
- }
-
- swfdec_audio_decoder_uncompressed_upscale (decoder, tmp);
- swfdec_buffer_unref (tmp);
-}
-
-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 (guint type, SwfdecAudioFormat format)
-{
- SwfdecAudioDecoderUncompressed *dec;
-
- if (type != SWFDEC_AUDIO_CODEC_UNDEFINED &&
- type != SWFDEC_AUDIO_CODEC_UNCOMPRESSED)
- return NULL;
- if (type == SWFDEC_AUDIO_CODEC_UNDEFINED) {
- SWFDEC_WARNING ("endianness of audio unknown, assuming little endian");
- }
- dec = g_new (SwfdecAudioDecoderUncompressed, 1);
- if (swfdec_audio_format_is_16bit (format))
- 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;
-}
-
-/*** PUBLIC API ***/
-
-static SwfdecAudioDecoder *
-swfdec_audio_decoder_builtin_new (guint codec, SwfdecAudioFormat format)
-{
- SwfdecAudioDecoder *ret;
-
- ret = swfdec_audio_decoder_uncompressed_new (codec, format);
- if (ret == NULL)
- ret = swfdec_audio_decoder_adpcm_new (codec, format);
-
- return ret;
-}
-
-static gboolean
-swfdec_audio_decoder_builtin_prepare (guint codec, SwfdecAudioFormat format, char **detail)
-{
- return codec == SWFDEC_AUDIO_CODEC_UNCOMPRESSED ||
- codec == SWFDEC_AUDIO_CODEC_UNDEFINED ||
- codec == SWFDEC_AUDIO_CODEC_ADPCM;
-}
-
-static const struct {
- const char * name;
- SwfdecAudioDecoder * (* func) (guint, SwfdecAudioFormat);
- gboolean (* prepare) (guint, SwfdecAudioFormat, char **);
-} audio_codecs[] = {
- { "builtin", swfdec_audio_decoder_builtin_new, swfdec_audio_decoder_builtin_prepare },
-#ifdef HAVE_GST
- { "gst", swfdec_audio_decoder_gst_new, swfdec_audio_decoder_gst_prepare },
-#endif
-};
-
-gboolean
-swfdec_audio_decoder_prepare (guint codec, SwfdecAudioFormat format, char **missing)
-{
- char *detail = NULL, *s = NULL;
- guint i;
-
- for (i = 0; i < G_N_ELEMENTS (audio_codecs); i++) {
- if (audio_codecs[i].prepare (codec, format, &s)) {
- g_free (detail);
- g_free (s);
- if (missing)
- *missing = NULL;
- return TRUE;
- }
- if (s) {
- if (detail == NULL)
- detail = s;
- else
- g_free (s);
- s = NULL;
- }
- }
- if (missing)
- *missing = detail;
- return FALSE;
-}
-
-/**
- * swfdec_audio_decoder_new:
- * @format: #SwfdecAudioCodec 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 (guint codec, SwfdecAudioFormat format)
-{
- SwfdecAudioDecoder *ret = NULL;
- guint i;
-
- g_return_val_if_fail (SWFDEC_IS_AUDIO_FORMAT (format), NULL);
-
- for (i = 0; i < G_N_ELEMENTS (audio_codecs); i++) {
- ret = audio_codecs[i].func (codec, format);
- if (ret)
- break;
- }
-
- if (ret) {
- ret->codec = codec;
- 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 codec %u", codec);
- 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_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)
-{
- SwfdecBuffer *ret;
-
- g_return_val_if_fail (decoder != NULL, NULL);
-
- ret = decoder->pull (decoder);
- if (ret == NULL)
- return NULL;
- return ret;
-}
-
diff --git a/swfdec/swfdec_codec_audio.h b/swfdec/swfdec_codec_audio.h
deleted file mode 100644
index b117ab2..0000000
--- a/swfdec/swfdec_codec_audio.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* 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 <swfdec/swfdec_audio_internal.h>
-#include <swfdec/swfdec_buffer.h>
-
-typedef struct _SwfdecAudioDecoder SwfdecAudioDecoder;
-
-#define SWFDEC_AUDIO_CODEC_UNDEFINED 0
-#define SWFDEC_AUDIO_CODEC_ADPCM 1
-#define SWFDEC_AUDIO_CODEC_MP3 2
-#define SWFDEC_AUDIO_CODEC_UNCOMPRESSED 3
-#define SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ 5
-#define SWFDEC_AUDIO_CODEC_NELLYMOSER 6
-
-struct _SwfdecAudioDecoder {
- guint codec;
- void (* push) (SwfdecAudioDecoder * decoder,
- SwfdecBuffer * buffer);
- SwfdecBuffer * (* pull) (SwfdecAudioDecoder * decoder);
- void (* free) (SwfdecAudioDecoder * decoder);
-};
-
-gboolean swfdec_audio_decoder_prepare (guint codec,
- SwfdecAudioFormat format,
- char ** missing);
-SwfdecAudioDecoder * swfdec_audio_decoder_new (guint codec,
- SwfdecAudioFormat format);
-void swfdec_audio_decoder_free (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/swfdec/swfdec_codec_gst.c b/swfdec/swfdec_codec_gst.c
index f48dfd7..054d06c 100644
--- a/swfdec/swfdec_codec_gst.c
+++ b/swfdec/swfdec_codec_gst.c
@@ -21,10 +21,9 @@
#include "config.h"
#endif
#include <string.h>
-#include <gst/gst.h>
#include <gst/pbutils/pbutils.h>
-#include "swfdec_codec_audio.h"
+#include "swfdec_codec_gst.h"
#include "swfdec_codec_video.h"
#include "swfdec_debug.h"
#include "swfdec_internal.h"
@@ -32,34 +31,6 @@
/*** CAPS MATCHING ***/
static GstCaps *
-swfdec_audio_decoder_get_caps (guint codec, SwfdecAudioFormat format)
-{
- GstCaps *caps;
- char *s;
-
- switch (codec) {
- case SWFDEC_AUDIO_CODEC_MP3:
- s = g_strdup ("audio/mpeg, mpegversion=(int)1, layer=(int)3");
- break;
- case SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ:
- s = g_strdup ("audio/x-nellymoser, rate=8000, channels=1");
- break;
- case SWFDEC_AUDIO_CODEC_NELLYMOSER:
- s = g_strdup_printf ("audio/x-nellymoser, rate=%d, channels=%d",
- swfdec_audio_format_get_rate (format),
- swfdec_audio_format_get_channels (format));
- break;
- default:
- return NULL;
- }
-
- caps = gst_caps_from_string (s);
- g_assert (caps);
- g_free (s);
- return caps;
-}
-
-static GstCaps *
swfdec_video_decoder_get_caps (guint codec)
{
GstCaps *caps;
@@ -80,12 +51,7 @@ swfdec_video_decoder_get_caps (guint codec)
/*** BUFFER ***/
-/* NB: references argument more than once */
-#define swfdec_buffer_new_from_gst(buffer) \
- swfdec_buffer_new_full (GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), \
- (SwfdecBufferFreeFunc) gst_mini_object_unref, (buffer))
-
-static GstBuffer *
+GstBuffer *
swfdec_gst_buffer_new (SwfdecBuffer *buffer)
{
/* FIXME: make this a zero-copy operation */
@@ -160,7 +126,7 @@ swfdec_gst_compare_features (gconstpointer a_, gconstpointer b_)
return strcmp (gst_plugin_feature_get_name (a), gst_plugin_feature_get_name (b));
}
-static GstElementFactory *
+GstElementFactory *
swfdec_gst_get_element_factory (GstCaps *caps)
{
GstElementFactory *ret;
@@ -236,13 +202,6 @@ error:
/*** DECODER ***/
-typedef struct {
- GstElement * decoder;
- GstPad * src;
- GstPad * sink;
- GQueue * queue; /* all the stored output GstBuffers */
-} SwfdecGstDecoder;
-
static GstFlowReturn
swfdec_gst_chain_func (GstPad *pad, GstBuffer *buffer)
{
@@ -253,7 +212,7 @@ swfdec_gst_chain_func (GstPad *pad, GstBuffer *buffer)
return GST_FLOW_OK;
}
-static gboolean
+gboolean
swfdec_gst_decoder_init (SwfdecGstDecoder *dec, const char *name, GstCaps *srccaps, GstCaps *sinkcaps)
{
if (name) {
@@ -285,7 +244,7 @@ swfdec_gst_decoder_init (SwfdecGstDecoder *dec, const char *name, GstCaps *srcca
return TRUE;
}
-static void
+void
swfdec_gst_decoder_finish (SwfdecGstDecoder *dec)
{
if (dec->decoder) {
@@ -311,7 +270,7 @@ swfdec_gst_decoder_finish (SwfdecGstDecoder *dec)
}
}
-static gboolean
+gboolean
swfdec_gst_decoder_push (SwfdecGstDecoder *dec, GstBuffer *buffer)
{
GstFlowReturn ret;
@@ -338,134 +297,18 @@ swfdec_gst_decoder_push (SwfdecGstDecoder *dec, GstBuffer *buffer)
return FALSE;
}
-static void
+void
swfdec_gst_decoder_push_eos (SwfdecGstDecoder *dec)
{
gst_pad_push_event (dec->src, gst_event_new_eos ());
}
-static GstBuffer *
+GstBuffer *
swfdec_gst_decoder_pull (SwfdecGstDecoder *dec)
{
return g_queue_pop_head (dec->queue);
}
-/*** AUDIO ***/
-
-typedef struct _SwfdecGstAudio SwfdecGstAudio;
-struct _SwfdecGstAudio {
- SwfdecAudioDecoder decoder;
-
- gboolean error;
- SwfdecGstDecoder dec;
- SwfdecGstDecoder convert;
- SwfdecGstDecoder resample;
-};
-
-static void
-swfdec_audio_decoder_gst_free (SwfdecAudioDecoder *dec)
-{
- SwfdecGstAudio *player = (SwfdecGstAudio *) dec;
-
- swfdec_gst_decoder_finish (&player->dec);
- swfdec_gst_decoder_finish (&player->convert);
- swfdec_gst_decoder_finish (&player->resample);
-
- g_slice_free (SwfdecGstAudio, player);
-}
-
-static void
-swfdec_audio_decoder_gst_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
-{
- SwfdecGstAudio *player = (SwfdecGstAudio *) dec;
- GstBuffer *buf;
-
- if (player->error)
- return;
- if (buffer == NULL) {
- swfdec_gst_decoder_push_eos (&player->dec);
- } else {
- swfdec_buffer_ref (buffer);
- buf = swfdec_gst_buffer_new (buffer);
- if (!swfdec_gst_decoder_push (&player->dec, buf))
- goto error;
- }
- while ((buf = swfdec_gst_decoder_pull (&player->dec))) {
- if (!swfdec_gst_decoder_push (&player->convert, buf))
- goto error;
- }
- while ((buf = swfdec_gst_decoder_pull (&player->convert))) {
- if (!swfdec_gst_decoder_push (&player->resample, buf))
- goto error;
- }
- return;
-
-error:
- SWFDEC_ERROR ("error pushing");
- player->error = TRUE;
-}
-
-static SwfdecBuffer *
-swfdec_audio_decoder_gst_pull (SwfdecAudioDecoder *dec)
-{
- SwfdecGstAudio *player = (SwfdecGstAudio *) dec;
- GstBuffer *buf;
-
- if (player->error)
- return NULL;
- buf = swfdec_gst_decoder_pull (&player->resample);
- if (buf == NULL)
- return NULL;
- return swfdec_buffer_new_from_gst (buf);
-}
-
-SwfdecAudioDecoder *
-swfdec_audio_decoder_gst_new (guint type, SwfdecAudioFormat format)
-{
- SwfdecGstAudio *player;
- GstCaps *srccaps, *sinkcaps;
-
- srccaps = swfdec_audio_decoder_get_caps (type, format);
- if (srccaps == NULL)
- return NULL;
-
- player = g_slice_new0 (SwfdecGstAudio);
- player->decoder.pull = swfdec_audio_decoder_gst_pull;
- player->decoder.push = swfdec_audio_decoder_gst_push;
- player->decoder.free = swfdec_audio_decoder_gst_free;
-
- /* create decoder */
- sinkcaps = gst_caps_from_string ("audio/x-raw-int");
- g_assert (sinkcaps);
- if (!swfdec_gst_decoder_init (&player->dec, NULL, srccaps, sinkcaps))
- goto error;
- /* create audioconvert */
- gst_caps_unref (srccaps);
- srccaps = sinkcaps;
- sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, channels=2");
- g_assert (sinkcaps);
- if (!swfdec_gst_decoder_init (&player->convert, "audioconvert", srccaps, sinkcaps))
- goto error;
- /* create audiorate */
- gst_caps_unref (srccaps);
- srccaps = sinkcaps;
- sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, rate=44100, channels=2");
- g_assert (sinkcaps);
- if (!swfdec_gst_decoder_init (&player->resample, "audioresample", srccaps, sinkcaps))
- goto error;
- g_object_set_data (G_OBJECT (player->resample.sink), "swfdec-player", player);
-
- gst_caps_unref (srccaps);
- gst_caps_unref (sinkcaps);
- return &player->decoder;
-
-error:
- swfdec_audio_decoder_gst_free (&player->decoder);
- gst_caps_unref (srccaps);
- gst_caps_unref (sinkcaps);
- return NULL;
-}
-
/*** VIDEO ***/
/* NB: We don't put a colorspace tansform here, we just assume that the codecs
@@ -609,30 +452,6 @@ swfdec_video_decoder_gst_new (guint codec)
/*** MISSING PLUGIN SUPPORT ***/
gboolean
-swfdec_audio_decoder_gst_prepare (guint codec, SwfdecAudioFormat format, char **detail)
-{
- GstElementFactory *factory;
- GstCaps *caps;
-
- /* Check if we can handle the format at all. If not, no plugin will help us. */
- caps = swfdec_audio_decoder_get_caps (codec, format);
- if (caps == NULL)
- return FALSE;
-
- /* If we can already handle it, woohoo! */
- factory = swfdec_gst_get_element_factory (caps);
- if (factory != NULL) {
- gst_object_unref (factory);
- return TRUE;
- }
-
- /* need to install plugins... */
- *detail = gst_missing_decoder_installer_detail_new (caps);
- gst_caps_unref (caps);
- return FALSE;
-}
-
-gboolean
swfdec_video_decoder_gst_prepare (guint codec, char **detail)
{
GstElementFactory *factory;
diff --git a/swfdec/swfdec_decoder.c b/swfdec/swfdec_decoder.c
index 81e4c22..4991ea7 100644
--- a/swfdec/swfdec_decoder.c
+++ b/swfdec/swfdec_decoder.c
@@ -23,9 +23,9 @@
#include <string.h>
-#include "swfdec_codec_audio.h"
-#include "swfdec_codec_video.h"
#include "swfdec_decoder.h"
+#include "swfdec_audio_decoder.h"
+#include "swfdec_codec_video.h"
#include "swfdec_debug.h"
#include "swfdec_decoder.h"
#include "swfdec_image.h"
diff --git a/swfdec/swfdec_flv_decoder.c b/swfdec/swfdec_flv_decoder.c
index 30f32a6..a8d1aba 100644
--- a/swfdec/swfdec_flv_decoder.c
+++ b/swfdec/swfdec_flv_decoder.c
@@ -22,6 +22,7 @@
#endif
#include "swfdec_flv_decoder.h"
+#include "swfdec_audio_decoder.h"
#include "swfdec_audio_internal.h"
#include "swfdec_bits.h"
#include "swfdec_debug.h"
diff --git a/swfdec/swfdec_flv_decoder.h b/swfdec/swfdec_flv_decoder.h
index 0c27d50..3bf7b4b 100644
--- a/swfdec/swfdec_flv_decoder.h
+++ b/swfdec/swfdec_flv_decoder.h
@@ -20,7 +20,7 @@
#ifndef __SWFDEC_FLV_DECODER_H__
#define __SWFDEC_FLV_DECODER_H__
-#include <swfdec/swfdec_codec_audio.h>
+#include <swfdec/swfdec_audio_internal.h>
#include <swfdec/swfdec_codec_video.h>
#include <swfdec/swfdec_decoder.h>
diff --git a/swfdec/swfdec_internal.h b/swfdec/swfdec_internal.h
index 15bb69b..126e391 100644
--- a/swfdec/swfdec_internal.h
+++ b/swfdec/swfdec_internal.h
@@ -23,24 +23,11 @@
#define _SWFDEC_INTERNAL_H_
#include <swfdec/swfdec_types.h>
-#include <swfdec/swfdec_codec_audio.h>
#include <swfdec/swfdec_codec_video.h>
G_BEGIN_DECLS
-/* audio codecs */
-
-SwfdecAudioDecoder * swfdec_audio_decoder_adpcm_new (guint type,
- SwfdecAudioFormat format);
-#ifdef HAVE_GST
-SwfdecAudioDecoder * swfdec_audio_decoder_gst_new (guint type,
- SwfdecAudioFormat format);
-gboolean swfdec_audio_decoder_gst_prepare (guint codec,
- SwfdecAudioFormat format,
- char ** detail);
-#endif
-
/* video codecs */
SwfdecVideoDecoder * swfdec_video_decoder_screen_new (guint format);
diff --git a/swfdec/swfdec_sound.c b/swfdec/swfdec_sound.c
index a40081b..88cb175 100644
--- a/swfdec/swfdec_sound.c
+++ b/swfdec/swfdec_sound.c
@@ -23,8 +23,9 @@
#endif
#include <string.h>
-#include "swfdec_audio_internal.h"
#include "swfdec_sound.h"
+#include "swfdec_audio_decoder.h"
+#include "swfdec_audio_internal.h"
#include "swfdec_bits.h"
#include "swfdec_buffer.h"
#include "swfdec_button.h"
@@ -179,7 +180,7 @@ swfdec_sound_get_decoded (SwfdecSound *sound)
while ((tmp = swfdec_audio_decoder_pull (decoder))) {
swfdec_buffer_queue_push (queue, tmp);
}
- swfdec_audio_decoder_free (decoder);
+ g_object_unref (decoder);
depth = swfdec_buffer_queue_get_depth (queue);
if (depth == 0) {
SWFDEC_ERROR ("decoding didn't produce any data, bailing");
diff --git a/swfdec/swfdec_system_as.c b/swfdec/swfdec_system_as.c
index 1e29f50..a385060 100644
--- a/swfdec/swfdec_system_as.c
+++ b/swfdec/swfdec_system_as.c
@@ -25,7 +25,7 @@
#include "swfdec_as_internal.h"
#include "swfdec_as_string.h"
#include "swfdec_as_strings.h"
-#include "swfdec_codec_audio.h"
+#include "swfdec_audio_decoder.h"
#include "swfdec_debug.h"
#include "swfdec_player_internal.h"
commit 3977f8d073b9959aae929b6ca61533384482fecb
Author: Benjamin Otte <otte at gnome.org>
Date: Mon May 26 12:07:03 2008 +0200
remove unused header
diff --git a/swfdec/swfdec_sound.h b/swfdec/swfdec_sound.h
index e7b202c..f3de014 100644
--- a/swfdec/swfdec_sound.h
+++ b/swfdec/swfdec_sound.h
@@ -23,7 +23,6 @@
#define _SWFDEC_SOUND_H_
#include <swfdec/swfdec_character.h>
-#include <swfdec/swfdec_codec_audio.h>
#include <swfdec/swfdec_swf_decoder.h>
#include <swfdec/swfdec_types.h>
commit af1ae4b8afe41c124b685375a71db164a7045457
Author: Benjamin Otte <otte at gnome.org>
Date: Sun May 25 18:39:13 2008 +0200
remove unused typedef
diff --git a/swfdec/swfdec_codec_audio.h b/swfdec/swfdec_codec_audio.h
index be32bf4..b117ab2 100644
--- a/swfdec/swfdec_codec_audio.h
+++ b/swfdec/swfdec_codec_audio.h
@@ -33,8 +33,6 @@ typedef struct _SwfdecAudioDecoder SwfdecAudioDecoder;
#define SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ 5
#define SWFDEC_AUDIO_CODEC_NELLYMOSER 6
-typedef SwfdecAudioDecoder * (SwfdecAudioDecoderNewFunc) (guint type, gboolean width,
- SwfdecAudioFormat format);
struct _SwfdecAudioDecoder {
guint codec;
void (* push) (SwfdecAudioDecoder * decoder,
More information about the Swfdec-commits
mailing list