[Swfdec] 13 commits - libswfdec/Makefile.am libswfdec/swfdec_decoder.c libswfdec/swfdec_decoder.h libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_flv_decoder.h libswfdec/swfdec_image.c libswfdec/swfdec_image_decoder.c libswfdec/swfdec_image_decoder.h libswfdec/swfdec_image.h libswfdec/swfdec_loader.c libswfdec/swfdec_loader.h libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h libswfdec/swfdec_net_stream.c libswfdec/swfdec_player.c libswfdec/swfdec_resource.c libswfdec/swfdec_swf_decoder.c test/dump.c

Benjamin Otte company at kemper.freedesktop.org
Mon Nov 12 09:24:07 PST 2007


 libswfdec/Makefile.am            |    2 
 libswfdec/swfdec_decoder.c       |   16 ++++-
 libswfdec/swfdec_decoder.h       |    3 
 libswfdec/swfdec_flv_decoder.c   |   19 +++---
 libswfdec/swfdec_flv_decoder.h   |    1 
 libswfdec/swfdec_image.c         |   29 ++++++---
 libswfdec/swfdec_image.h         |    1 
 libswfdec/swfdec_image_decoder.c |  123 +++++++++++++++++++++++++++++++++++++++
 libswfdec/swfdec_image_decoder.h |   59 ++++++++++++++++++
 libswfdec/swfdec_loader.c        |    6 +
 libswfdec/swfdec_loader.h        |    4 -
 libswfdec/swfdec_movie.c         |   25 +++++++
 libswfdec/swfdec_movie.h         |    1 
 libswfdec/swfdec_net_stream.c    |    7 --
 libswfdec/swfdec_player.c        |    2 
 libswfdec/swfdec_resource.c      |   51 ++++++++++------
 libswfdec/swfdec_swf_decoder.c   |   13 ++++
 test/dump.c                      |    2 
 18 files changed, 322 insertions(+), 42 deletions(-)

New commits:
commit c88c1cbe0b7d222e5915e92fa8f94f125434f48c
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 18:00:11 2007 +0100

    always schedule onLoadInit execution, as it's where we set the image

diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index 64bb1cd..d5be854 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -105,7 +105,7 @@ swfdec_resource_loader_target_image (SwfdecResource *instance)
 }
 
 /* NB: name must be GC'ed */
-static SwfdecSpriteMovie *
+static void
 swfdec_resource_emit_signal (SwfdecResource *resource, const char *name, gboolean progress, 
     SwfdecAsValue *args, guint n_args)
 {
@@ -115,14 +115,19 @@ swfdec_resource_emit_signal (SwfdecResource *resource, const char *name, gboolea
   SwfdecAsValue vals[n_args + skip];
 
   if (resource->clip_loader == NULL)
-    return NULL;
+    return;
   cx = SWFDEC_AS_OBJECT (resource->clip_loader)->context;
   g_assert (resource->target);
   movie = swfdec_action_lookup_object (cx, SWFDEC_PLAYER (cx)->roots->data, 
       resource->target, resource->target + strlen (resource->target));
   if (!SWFDEC_IS_SPRITE_MOVIE (movie)) {
     SWFDEC_DEBUG ("no movie, not emitting signal");
-    return NULL;
+    return;
+  }
+  if (name == SWFDEC_AS_STR_onLoadInit &&
+      movie != SWFDEC_AS_OBJECT (resource->movie)) {
+    SWFDEC_INFO ("not emitting onLoadInit - the movie is different");
+    return;
   }
 
   SWFDEC_AS_VALUE_SET_STRING (&vals[0], name);
@@ -147,7 +152,6 @@ swfdec_resource_emit_signal (SwfdecResource *resource, const char *name, gboolea
     memcpy (&vals[skip], args, sizeof (SwfdecAsValue) * n_args);
   swfdec_as_object_call (SWFDEC_AS_OBJECT (resource->clip_loader), SWFDEC_AS_STR_broadcastMessage, 
       n_args + skip, vals, NULL);
-  return SWFDEC_SPRITE_MOVIE (movie);
 }
 
 static void
@@ -311,7 +315,6 @@ swfdec_resource_loader_target_eof (SwfdecLoaderTarget *target, SwfdecLoader *loa
 {
   SwfdecResource *resource = SWFDEC_RESOURCE (target);
   SwfdecAsValue val;
-  SwfdecSpriteMovie *movie;
 
   swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadProgress, TRUE, NULL, 0);
   if (resource->decoder) {
@@ -321,14 +324,8 @@ swfdec_resource_loader_target_eof (SwfdecLoaderTarget *target, SwfdecLoader *loa
       swfdec_loader_set_data_type (loader, dec->data_type);
   }
   SWFDEC_AS_VALUE_SET_INT (&val, 0); /* FIXME */
-  movie = swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadComplete, FALSE, &val, 1);
-  /* FIXME: I bet this is wrong for figuring out if movies should emit onLoadInit */
-  if (resource->clip_loader == NULL ||
-      movie != resource->movie) {
-    resource->state = SWFDEC_RESOURCE_DONE;
-  } else {
-    resource->state = SWFDEC_RESOURCE_COMPLETE;
-  }
+  swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadComplete, FALSE, &val, 1);
+  resource->state = SWFDEC_RESOURCE_COMPLETE;
 }
 
 static void
@@ -551,20 +548,18 @@ swfdec_resource_load (SwfdecPlayer *player, const char *target, const char *url,
 gboolean
 swfdec_resource_emit_on_load_init (SwfdecResource *resource)
 {
-  SwfdecMovie *movie;
-
   g_return_val_if_fail (SWFDEC_IS_RESOURCE (resource), FALSE);
 
   if (resource->state != SWFDEC_RESOURCE_COMPLETE)
     return FALSE;
 
-  movie = SWFDEC_MOVIE (swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadInit, FALSE, NULL, 0));
+  swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadInit, FALSE, NULL, 0);
   resource->state = SWFDEC_RESOURCE_DONE;
-  if (movie && SWFDEC_IS_IMAGE_DECODER (resource->decoder)) {
+  if (resource->movie && SWFDEC_IS_IMAGE_DECODER (resource->decoder)) {
     SwfdecImage *image = SWFDEC_IMAGE_DECODER (resource->decoder)->image;
     if (image) {
-      movie->image = g_object_ref (image);
-      swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_CONTENTS);
+      SWFDEC_MOVIE (resource->movie)->image = g_object_ref (image);
+      swfdec_movie_queue_update (SWFDEC_MOVIE (resource->movie), SWFDEC_MOVIE_INVALID_CONTENTS);
     }
   }
   /* free now unneeded resources */
commit 617e03ee5b7af3d2ff46a5d03ec80b7ca6203b29
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 17:59:40 2007 +0100

    only pop as many actions as exist
    
    off-by-one error here

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 7d68208..ea6cb4b 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -344,7 +344,7 @@ swfdec_player_compress_actions (SwfdecRingBuffer *buffer)
   SwfdecPlayerAction *action, tmp;
   guint i = 0;
 
-  for (i = swfdec_ring_buffer_get_n_elements (buffer) + 1; i > 0; i--) {
+  for (i = swfdec_ring_buffer_get_n_elements (buffer); i > 0; i--) {
     action = swfdec_ring_buffer_pop (buffer);
     g_assert (action);
     if (action->movie == NULL)
commit 60b6471a70c2e0cf9bf9c872022b85544ffe9ed5
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 17:24:17 2007 +0100

    also copy matrix state when replacing movies

diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index 51ebff0..64bb1cd 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -173,11 +173,16 @@ swfdec_resource_replace_movie (SwfdecSpriteMovie *movie, SwfdecResource *resourc
   if (copy == NULL)
     return FALSE;
   copy->original_name = mov->original_name;
+  copy->modified = mov->modified;
+  copy->xscale = mov->xscale;
+  copy->yscale = mov->yscale;
+  copy->rotation = mov->rotation;
   /* FIXME: are events copied? If so, wouldn't that be a security issue? */
   swfdec_movie_set_static_properties (copy, &mov->original_transform,
       &mov->original_ctrans, mov->original_ratio, mov->clip_depth, 
       mov->blend_mode, NULL);
   swfdec_movie_remove (mov);
+  swfdec_movie_queue_update (copy, SWFDEC_MOVIE_INVALID_MATRIX);
   return SWFDEC_SPRITE_MOVIE (copy);
 }
 
commit 74c1e34359f4ecfbe78896a42ff6bf3f79b27d14
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 17:23:56 2007 +0100

    set loader size on decoder
    
    This is needed to report the correct size when loading images

diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index e6ed60d..51ebff0 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -252,7 +252,11 @@ swfdec_resource_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *l
     if (dec == NULL) {
       SWFDEC_ERROR ("no decoder found for format");
     } else {
+      glong total;
       resource->decoder = dec;
+      total = swfdec_loader_get_size (loader);
+      if (total >= 0)
+	dec->bytes_total = total;
     }
   }
   while (swfdec_buffer_queue_get_depth (loader->queue)) {
commit d53a117dd399129bc205b3c1d60f2519433eba96
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 14:16:41 2007 +0100

    make the movie display the loaded image

diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index e24c512..e6ed60d 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -33,6 +33,7 @@
 #include "swfdec_debug.h"
 #include "swfdec_decoder.h"
 #include "swfdec_flash_security.h"
+#include "swfdec_image_decoder.h"
 #include "swfdec_loader_internal.h"
 #include "swfdec_loadertarget.h"
 #include "swfdec_movie_clip_loader.h"
@@ -541,13 +542,22 @@ swfdec_resource_load (SwfdecPlayer *player, const char *target, const char *url,
 gboolean
 swfdec_resource_emit_on_load_init (SwfdecResource *resource)
 {
+  SwfdecMovie *movie;
+
   g_return_val_if_fail (SWFDEC_IS_RESOURCE (resource), FALSE);
 
   if (resource->state != SWFDEC_RESOURCE_COMPLETE)
     return FALSE;
 
-  swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadInit, FALSE, NULL, 0);
+  movie = SWFDEC_MOVIE (swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadInit, FALSE, NULL, 0));
   resource->state = SWFDEC_RESOURCE_DONE;
+  if (movie && SWFDEC_IS_IMAGE_DECODER (resource->decoder)) {
+    SwfdecImage *image = SWFDEC_IMAGE_DECODER (resource->decoder)->image;
+    if (image) {
+      movie->image = g_object_ref (image);
+      swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_CONTENTS);
+    }
+  }
   /* free now unneeded resources */
   if (resource->clip_loader) {
     g_object_unref (resource->clip_loader);
commit 63bd88b77ee4201fc3cc4a32bba7f0a9b6a6a399
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 14:09:03 2007 +0100

    render an image, if one is set

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 2f79b06..1aeb0bf 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -35,6 +35,7 @@
 #include "swfdec_draw.h"
 #include "swfdec_event.h"
 #include "swfdec_graphic.h"
+#include "swfdec_image.h"
 #include "swfdec_loader_internal.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_sprite.h"
@@ -128,6 +129,12 @@ swfdec_movie_update_extents (SwfdecMovie *movie)
   SwfdecRect *extents = &movie->extents;
 
   *rect = movie->draw_extents;
+  if (movie->image) {
+    SwfdecRect image_extents = { 0, 0, 
+      movie->image->width * SWFDEC_TWIPS_SCALE_FACTOR,
+      movie->image->height * SWFDEC_TWIPS_SCALE_FACTOR };
+    swfdec_rect_union (rect, rect, &image_extents);
+  }
   for (walk = movie->list; walk; walk = walk->next) {
     swfdec_rect_union (rect, rect, &SWFDEC_MOVIE (walk->data)->extents);
   }
@@ -880,6 +887,20 @@ swfdec_movie_render (SwfdecMovie *movie, cairo_t *cr,
     swfdec_draw_paint (draw, cr, &trans);
   }
 
+  /* if the movie loaded an image, draw it here now */
+  if (movie->image) {
+    cairo_surface_t *surface = swfdec_image_create_surface_transformed (movie->image,
+	&trans);
+    if (surface) {
+      static const cairo_matrix_t matrix = { 1.0 / SWFDEC_TWIPS_SCALE_FACTOR, 0, 0, 1.0 / SWFDEC_TWIPS_SCALE_FACTOR, 0, 0 };
+      cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
+      SWFDEC_LOG ("rendering loaded image");
+      cairo_pattern_set_matrix (pattern, &matrix);
+      cairo_set_source (cr, pattern);
+      cairo_paint (cr);
+    }
+  }
+
   /* draw the children movies */
   for (g = movie->list; g; g = g_list_next (g)) {
     SwfdecMovie *child = g->data;
@@ -1004,6 +1025,10 @@ swfdec_movie_dispose (GObject *object)
   g_slist_free (movie->variable_listeners);
   movie->variable_listeners = NULL;
 
+  if (movie->image) {
+    g_object_unref (movie->image);
+    movie->image = NULL;
+  }
   g_slist_foreach (movie->draws, (GFunc) g_object_unref, NULL);
   g_slist_free (movie->draws);
   movie->draws = NULL;
diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index 17a2f3b..380a32a 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -134,6 +134,7 @@ struct _SwfdecMovie {
 
   /* drawing state */
   /* FIXME: could it be that shape drawing (SwfdecGraphicMovie etc) uses these same objects? */
+  SwfdecImage *		image;			/* image loaded via loadMovie */
   SwfdecRect		draw_extents;		/* extents of the items in the following list */
   GSList *		draws;			/* all the items to draw */
   SwfdecDraw *		draw_fill;	      	/* current fill style or NULL */
commit 3cc0c51d81610bcbf081bc9e68b0319d91b7da07
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 14:08:49 2007 +0100

    create an ImageDecoder for images

diff --git a/libswfdec/swfdec_decoder.c b/libswfdec/swfdec_decoder.c
index 96648e3..24bbda0 100644
--- a/libswfdec/swfdec_decoder.c
+++ b/libswfdec/swfdec_decoder.c
@@ -25,7 +25,8 @@
 #include "swfdec_decoder.h"
 #include "swfdec_debug.h"
 #include "swfdec_decoder.h"
-#include "swfdec_flv_decoder.h"
+#include "swfdec_image.h"
+#include "swfdec_image_decoder.h"
 #include "swfdec_swf_decoder.h"
 
 
@@ -64,6 +65,8 @@ swfdec_decoder_new (SwfdecPlayer *player, const SwfdecBuffer *buffer)
       data[2] == 'V') {
     retval = g_object_new (SWFDEC_TYPE_FLV_DECODER, NULL);
 #endif
+  } else if (swfdec_image_detect (data) != SWFDEC_IMAGE_TYPE_UNKNOWN) {
+    retval = g_object_new (SWFDEC_TYPE_IMAGE_DECODER, NULL);
   } else {
     retval = NULL;
   }
commit 66e350039483f3a5265df74ee792e51e31f59a8c
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 13:15:35 2007 +0100

    add ImageDecoder to be able to decode images.
    
    the data type handling needed to be adjusted, too.

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 69ad762..6aa321f 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -72,6 +72,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
 	swfdec_graphic.c \
 	swfdec_graphic_movie.c \
 	swfdec_image.c \
+	swfdec_image_decoder.c \
 	swfdec_interval.c \
 	swfdec_key_as.c \
 	swfdec_load_object.c \
@@ -204,6 +205,7 @@ noinst_HEADERS = \
 	swfdec_graphic.h \
 	swfdec_graphic_movie.h \
 	swfdec_image.h \
+	swfdec_image_decoder.h \
 	swfdec_initialize.h \
 	swfdec_internal.h \
 	swfdec_interval.h \
diff --git a/libswfdec/swfdec_decoder.h b/libswfdec/swfdec_decoder.h
index 33f5a5f..7a93276 100644
--- a/libswfdec/swfdec_decoder.h
+++ b/libswfdec/swfdec_decoder.h
@@ -58,6 +58,7 @@ struct _SwfdecDecoder
   GObject		object;
 
   SwfdecPlayer *	player;		/* FIXME: only needed to get the JS Context, I want it gone */
+  SwfdecLoaderDataType	data_type;	/* type of the data we provide or UNKNOWN if not known yet */
   guint			rate;		/* rate per second in 256th */
   guint			width;		/* width of stream */
   guint			height;		/* guess */
diff --git a/libswfdec/swfdec_image_decoder.c b/libswfdec/swfdec_image_decoder.c
new file mode 100644
index 0000000..49443c9
--- /dev/null
+++ b/libswfdec/swfdec_image_decoder.c
@@ -0,0 +1,123 @@
+/* Swfdec
+ * Copyright (C) 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_image_decoder.h"
+#include "swfdec_debug.h"
+#include "swfdec_image.h"
+
+G_DEFINE_TYPE (SwfdecImageDecoder, swfdec_image_decoder, SWFDEC_TYPE_DECODER)
+
+static void
+swfdec_image_decoder_dispose (GObject *object)
+{
+  SwfdecImageDecoder *image = SWFDEC_IMAGE_DECODER (object);
+
+  if (image->queue) {
+    swfdec_buffer_queue_unref (image->queue);
+    image->queue = NULL;
+  }
+
+  if (image->image) {
+    g_object_unref (image->image);
+    image->image = NULL;
+  }
+
+  G_OBJECT_CLASS (swfdec_image_decoder_parent_class)->dispose (object);
+}
+
+static SwfdecStatus
+swfdec_image_decoder_parse (SwfdecDecoder *dec, SwfdecBuffer *buffer)
+{
+  SwfdecImageDecoder *image = SWFDEC_IMAGE_DECODER (dec);
+
+  if (image->queue == NULL)
+    image->queue = swfdec_buffer_queue_new ();
+  swfdec_buffer_queue_push (image->queue, buffer);
+  dec->bytes_loaded += buffer->length;
+  if (dec->bytes_loaded < dec->bytes_total)
+    dec->bytes_total = dec->bytes_loaded;
+  return 0;
+}
+
+/* FIXME: move this to swfdec_image API? */
+static gboolean
+swfdec_image_get_size (SwfdecImage *image, guint *w, guint *h)
+{
+  cairo_surface_t *surface;
+
+  surface = swfdec_image_create_surface (image);
+  if (surface == NULL)
+    return FALSE;
+
+  if (w)
+    *w = cairo_image_surface_get_width (surface);
+  if (h)
+    *h = cairo_image_surface_get_width (surface);
+
+  return TRUE;
+}
+
+static SwfdecStatus
+swfdec_image_decoder_eof (SwfdecDecoder *dec)
+{
+  SwfdecImageDecoder *image = SWFDEC_IMAGE_DECODER (dec);
+  SwfdecBuffer *buffer;
+
+  if (image->queue == NULL)
+    return 0;
+  /* FIXME: size checking */
+  buffer = swfdec_buffer_queue_pull (image->queue,
+      swfdec_buffer_queue_get_depth (image->queue));
+  swfdec_buffer_queue_unref (image->queue);
+  image->queue = NULL;
+  image->image = swfdec_image_new (buffer);
+  if (!swfdec_image_get_size (image->image, &dec->width, &dec->height))
+    return SWFDEC_STATUS_ERROR;
+  dec->frames_loaded = 1;
+  dec->frames_total = 1;
+  if (image->image->type == SWFDEC_IMAGE_TYPE_JPEG)
+    dec->data_type = SWFDEC_LOADER_DATA_JPEG;
+  else if (image->image->type == SWFDEC_IMAGE_TYPE_PNG)
+    dec->data_type = SWFDEC_LOADER_DATA_PNG;
+
+
+  return SWFDEC_STATUS_INIT | SWFDEC_STATUS_IMAGE;
+}
+
+static void
+swfdec_image_decoder_class_init (SwfdecImageDecoderClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  SwfdecDecoderClass *decoder_class = SWFDEC_DECODER_CLASS (class);
+
+  object_class->dispose = swfdec_image_decoder_dispose;
+
+  decoder_class->parse = swfdec_image_decoder_parse;
+  decoder_class->eof = swfdec_image_decoder_eof;
+}
+
+static void
+swfdec_image_decoder_init (SwfdecImageDecoder *s)
+{
+}
+
diff --git a/libswfdec/swfdec_image_decoder.h b/libswfdec/swfdec_image_decoder.h
new file mode 100644
index 0000000..b5f3a84
--- /dev/null
+++ b/libswfdec/swfdec_image_decoder.h
@@ -0,0 +1,59 @@
+/* Swfdec
+ * Copyright (C) 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_IMAGE_DECODER_H__
+#define __SWFDEC_IMAGE_DECODER_H__
+
+#include <glib.h>
+
+#include <libswfdec/swfdec_decoder.h>
+#include <libswfdec/swfdec_bits.h>
+#include <libswfdec/swfdec_types.h>
+#include <libswfdec/swfdec_rect.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecImageDecoder SwfdecImageDecoder;
+typedef struct _SwfdecImageDecoderClass SwfdecImageDecoderClass;
+
+#define SWFDEC_TYPE_IMAGE_DECODER                    (swfdec_image_decoder_get_type())
+#define SWFDEC_IS_IMAGE_DECODER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_IMAGE_DECODER))
+#define SWFDEC_IS_IMAGE_DECODER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_IMAGE_DECODER))
+#define SWFDEC_IMAGE_DECODER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_IMAGE_DECODER, SwfdecImageDecoder))
+#define SWFDEC_IMAGE_DECODER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_IMAGE_DECODER, SwfdecImageDecoderClass))
+#define SWFDEC_IMAGE_DECODER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_IMAGE_DECODER, SwfdecImageDecoderClass))
+
+struct _SwfdecImageDecoder
+{
+  SwfdecDecoder		decoder;
+
+  SwfdecBufferQueue *	queue;		/* keeps the data while decoding */
+  SwfdecImage *		image;		/* the image we display */
+};
+
+struct _SwfdecImageDecoderClass {
+  SwfdecDecoderClass	decoder_class;
+};
+
+GType		swfdec_image_decoder_get_type		(void);
+
+
+G_END_DECLS
+
+#endif
diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 618b9d7..7595c4e 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -62,6 +62,8 @@
  * @SWFDEC_LOADER_DATA_FLV: Data describing a Flash video stream.
  * @SWFDEC_LOADER_DATA_XML: Data in XML format.
  * @SWFDEC_LOADER_DATA_TEXT: Textual data.
+ * @SWFDEC_LOADER_DATA_JPEG: a JPEG image
+ * @SWFDEC_LOADER_DATA_PNG: a PNG image
  *
  * This type describes the different types of data that can be loaded inside 
  * Swfdec. Swfdec identifies its data streams and you can use the 
@@ -577,6 +579,10 @@ swfdec_loader_data_type_get_extension (SwfdecLoaderDataType type)
       return "xml";
     case SWFDEC_LOADER_DATA_TEXT:
       return "txt";
+    case SWFDEC_LOADER_DATA_JPEG:
+      return "jpg";
+    case SWFDEC_LOADER_DATA_PNG:
+      return "png";
     default:
       g_warning ("unknown data type %u", type);
       return "";
diff --git a/libswfdec/swfdec_loader.h b/libswfdec/swfdec_loader.h
index 9eb5b2a..0d0c6a4 100644
--- a/libswfdec/swfdec_loader.h
+++ b/libswfdec/swfdec_loader.h
@@ -31,7 +31,9 @@ typedef enum {
   SWFDEC_LOADER_DATA_SWF,
   SWFDEC_LOADER_DATA_FLV,
   SWFDEC_LOADER_DATA_XML,
-  SWFDEC_LOADER_DATA_TEXT
+  SWFDEC_LOADER_DATA_TEXT,
+  SWFDEC_LOADER_DATA_JPEG,
+  SWFDEC_LOADER_DATA_PNG
 } SwfdecLoaderDataType;
 
 /* NB: actal numbers in SwfdecLoaderRequest are important for GetURL2 action */
diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index 00816ca..e24c512 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -250,11 +250,8 @@ swfdec_resource_loader_target_parse (SwfdecLoaderTarget *target, SwfdecLoader *l
     swfdec_buffer_unref (buffer);
     if (dec == NULL) {
       SWFDEC_ERROR ("no decoder found for format");
-    } else if (SWFDEC_IS_SWF_DECODER (dec)) {
-      swfdec_loader_set_data_type (loader, SWFDEC_LOADER_DATA_SWF);
-      resource->decoder = dec;
     } else {
-      SWFDEC_FIXME ("implement handling of %s", G_OBJECT_TYPE_NAME (dec));
+      resource->decoder = dec;
     }
   }
   while (swfdec_buffer_queue_get_depth (loader->queue)) {
@@ -308,7 +305,10 @@ swfdec_resource_loader_target_eof (SwfdecLoaderTarget *target, SwfdecLoader *loa
 
   swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadProgress, TRUE, NULL, 0);
   if (resource->decoder) {
-    swfdec_decoder_eof (resource->decoder);
+    SwfdecDecoder *dec = resource->decoder;
+    swfdec_decoder_eof (dec);
+    if (dec->data_type != SWFDEC_LOADER_DATA_UNKNOWN)
+      swfdec_loader_set_data_type (loader, dec->data_type);
   }
   SWFDEC_AS_VALUE_SET_INT (&val, 0); /* FIXME */
   movie = swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadComplete, FALSE, &val, 1);
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index ae5311c..f079c54 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -234,6 +234,7 @@ swf_parse_header1 (SwfdecSwfDecoder * s)
   s->bytes_parsed = 8;
   s->state = SWFDEC_STATE_INIT2;
   swfdec_swf_decoder_deflate (s, rest);
+  dec->data_type = SWFDEC_LOADER_DATA_SWF;
 
   return SWFDEC_STATUS_OK;
 }
commit c4dd05264c289d66d70009cf1bf70905c3878b39
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 12:05:10 2007 +0100

    split out image type detection

diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index a3094c9..661e341 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -663,6 +663,21 @@ swfdec_image_create_surface_transformed (SwfdecImage *image, const SwfdecColorTr
   return surface;
 }
 
+/* NB: must be at least SWFDEC_DECODER_DETECT_LENGTH bytes */
+SwfdecImageType
+swfdec_image_detect (const guint8 *data)
+{
+  g_return_val_if_fail (data != NULL, SWFDEC_IMAGE_TYPE_UNKNOWN);
+
+  if (data[0] == 0xFF && data[1] == 0xD8)
+    return SWFDEC_IMAGE_TYPE_JPEG2;
+  else if (data[0] == 89 && data[1] == 'P' &&
+      data[2] == 'N' && data[3] == 'G')
+    return SWFDEC_IMAGE_TYPE_PNG;
+  else
+    return SWFDEC_IMAGE_TYPE_UNKNOWN;
+}
+
 SwfdecImage *
 swfdec_image_new (SwfdecBuffer *buffer)
 {
@@ -674,12 +689,8 @@ swfdec_image_new (SwfdecBuffer *buffer)
   /* check type of the image */
   if (buffer->length < 4)
     goto fail;
-  if (buffer->data[0] == 0xFF && buffer->data[1] == 0xD8)
-    type = SWFDEC_IMAGE_TYPE_JPEG2;
-  else if (buffer->data[0] == 89 && buffer->data[1] == 'P' &&
-      buffer->data[2] == 'N' && buffer->data[3] == 'G')
-    type = SWFDEC_IMAGE_TYPE_PNG;
-  else
+  type = swfdec_image_detect (buffer->data);
+  if (type == SWFDEC_IMAGE_TYPE_UNKNOWN)
     goto fail;
 
   image = g_object_new (SWFDEC_TYPE_IMAGE, NULL);
diff --git a/libswfdec/swfdec_image.h b/libswfdec/swfdec_image.h
index 9e032ec..e648e08 100644
--- a/libswfdec/swfdec_image.h
+++ b/libswfdec/swfdec_image.h
@@ -66,6 +66,7 @@ struct _SwfdecImageClass {
 
 GType			swfdec_image_get_type		(void);
 
+SwfdecImageType		swfdec_image_detect		(const guint8 *		data);
 SwfdecImage *		swfdec_image_new		(SwfdecBuffer *		buffer);
 cairo_surface_t *	swfdec_image_create_surface	(SwfdecImage *		image);
 cairo_surface_t *	swfdec_image_create_surface_transformed 
commit 96c7c6738613dd92b4c43f9b4daa8871607f07dd
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 12:01:20 2007 +0100

    call swfdec_decoder_parse()

diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index ebd19ba..bb8e8b9 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -260,7 +260,6 @@ swfdec_net_stream_loader_target_parse (SwfdecLoaderTarget *target,
     SwfdecLoader *loader)
 {
   SwfdecNetStream *stream = SWFDEC_NET_STREAM (target);
-  SwfdecDecoderClass *klass;
   SwfdecStatus status;
   
   if (loader->state != SWFDEC_LOADER_STATE_EOF && swfdec_buffer_queue_get_depth (loader->queue) == 0) {
@@ -275,8 +274,6 @@ swfdec_net_stream_loader_target_parse (SwfdecLoaderTarget *target,
 	SWFDEC_AS_STR_status);
     swfdec_loader_set_data_type (loader, SWFDEC_LOADER_DATA_FLV);
   }
-  klass = SWFDEC_DECODER_GET_CLASS (stream->flvdecoder);
-  g_return_if_fail (klass->parse);
 
   status = SWFDEC_STATUS_OK;
   do {
@@ -284,7 +281,7 @@ swfdec_net_stream_loader_target_parse (SwfdecLoaderTarget *target,
     if (buffer == NULL)
       break;
     status &= ~SWFDEC_STATUS_NEEDBITS;
-    status |= klass->parse (SWFDEC_DECODER (stream->flvdecoder), buffer);
+    status |= swfdec_decoder_parse (SWFDEC_DECODER (stream->flvdecoder), buffer);
   } while ((status & (SWFDEC_STATUS_ERROR | SWFDEC_STATUS_EOF)) == 0);
 
   if (status & SWFDEC_STATUS_IMAGE)
commit 2ca365e6a7091ccdac1ed464c6c4d54490a2bfe1
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 12:00:25 2007 +0100

    add an EOF vfunc to SwfdecDecoder and use it

diff --git a/libswfdec/swfdec_decoder.c b/libswfdec/swfdec_decoder.c
index b17cb98..96648e3 100644
--- a/libswfdec/swfdec_decoder.c
+++ b/libswfdec/swfdec_decoder.c
@@ -86,4 +86,15 @@ swfdec_decoder_parse (SwfdecDecoder *decoder, SwfdecBuffer *buffer)
   return klass->parse (decoder, buffer);
 }
 
+SwfdecStatus
+swfdec_decoder_eof (SwfdecDecoder *decoder)
+{
+  SwfdecDecoderClass *klass;
+
+  g_return_val_if_fail (SWFDEC_IS_DECODER (decoder), SWFDEC_STATUS_ERROR);
+
+  klass = SWFDEC_DECODER_GET_CLASS (decoder);
+  g_return_val_if_fail (klass->eof, SWFDEC_STATUS_ERROR);
+  return klass->eof (decoder);
+}
 
diff --git a/libswfdec/swfdec_decoder.h b/libswfdec/swfdec_decoder.h
index 7483df1..33f5a5f 100644
--- a/libswfdec/swfdec_decoder.h
+++ b/libswfdec/swfdec_decoder.h
@@ -73,6 +73,7 @@ struct _SwfdecDecoderClass
 
   SwfdecStatus		(* parse)		(SwfdecDecoder *	decoder,
 						 SwfdecBuffer *		buffer);
+  SwfdecStatus		(* eof)			(SwfdecDecoder *	decoder);
 };
 
 GType		swfdec_decoder_get_type		(void);
@@ -83,6 +84,7 @@ SwfdecDecoder *	swfdec_decoder_new		(SwfdecPlayer *		player,
 
 SwfdecStatus	swfdec_decoder_parse		(SwfdecDecoder *	decoder,
 						 SwfdecBuffer * 	buffer);
+SwfdecStatus	swfdec_decoder_eof		(SwfdecDecoder *	decoder);
 
 
 G_END_DECLS
diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c
index 465852d..8caf2b6 100644
--- a/libswfdec/swfdec_flv_decoder.c
+++ b/libswfdec/swfdec_flv_decoder.c
@@ -433,6 +433,16 @@ swfdec_flv_decoder_parse (SwfdecDecoder *dec, SwfdecBuffer *buffer)
   return status;
 }
 
+static SwfdecStatus
+swfdec_flv_decoder_eof (SwfdecDecoder *dec)
+{
+  SwfdecFlvDecoder *flv = SWFDEC_FLV_DECODER (dec);
+
+  flv->state = SWFDEC_STATE_EOF;
+
+  return 0;
+}
+
 static void
 swfdec_flv_decoder_class_init (SwfdecFlvDecoderClass *class)
 {
@@ -442,6 +452,7 @@ swfdec_flv_decoder_class_init (SwfdecFlvDecoderClass *class)
   object_class->dispose = swfdec_flv_decoder_dispose;
 
   decoder_class->parse = swfdec_flv_decoder_parse;
+  decoder_class->eof = swfdec_flv_decoder_eof;
 }
 
 static void
@@ -602,11 +613,3 @@ swfdec_flv_decoder_is_eof (SwfdecFlvDecoder *flv)
   return flv->state == SWFDEC_STATE_EOF;
 }
 
-void
-swfdec_flv_decoder_eof (SwfdecFlvDecoder *flv)
-{
-  g_return_if_fail (SWFDEC_IS_FLV_DECODER (flv));
-
-  flv->state = SWFDEC_STATE_EOF;
-}
-
diff --git a/libswfdec/swfdec_flv_decoder.h b/libswfdec/swfdec_flv_decoder.h
index 5ad5114..635fea4 100644
--- a/libswfdec/swfdec_flv_decoder.h
+++ b/libswfdec/swfdec_flv_decoder.h
@@ -56,7 +56,6 @@ struct _SwfdecFlvDecoderClass {
 GType		swfdec_flv_decoder_get_type		(void);
 
 gboolean	swfdec_flv_decoder_is_eof		(SwfdecFlvDecoder *	flv);
-void		swfdec_flv_decoder_eof			(SwfdecFlvDecoder *	flv);
 
 SwfdecBuffer *	swfdec_flv_decoder_get_video  		(SwfdecFlvDecoder *	flv,
 							 guint			timestamp,
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 93493ca..ebd19ba 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -298,7 +298,7 @@ swfdec_net_stream_loader_target_eof (SwfdecLoaderTarget *target,
   SwfdecNetStream *stream = SWFDEC_NET_STREAM (target);
   guint first, last;
 
-  swfdec_flv_decoder_eof (stream->flvdecoder);
+  swfdec_decoder_eof (SWFDEC_DECODER (stream->flvdecoder));
   swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Buffer_Flush,
       SWFDEC_AS_STR_status);
   swfdec_net_stream_video_goto (stream, stream->current_time);
diff --git a/libswfdec/swfdec_resource.c b/libswfdec/swfdec_resource.c
index c93d151..00816ca 100644
--- a/libswfdec/swfdec_resource.c
+++ b/libswfdec/swfdec_resource.c
@@ -307,6 +307,9 @@ swfdec_resource_loader_target_eof (SwfdecLoaderTarget *target, SwfdecLoader *loa
   SwfdecSpriteMovie *movie;
 
   swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadProgress, TRUE, NULL, 0);
+  if (resource->decoder) {
+    swfdec_decoder_eof (resource->decoder);
+  }
   SWFDEC_AS_VALUE_SET_INT (&val, 0); /* FIXME */
   movie = swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadComplete, FALSE, &val, 1);
   /* FIXME: I bet this is wrong for figuring out if movies should emit onLoadInit */
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index 4a9b069..ae5311c 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -387,6 +387,17 @@ swfdec_swf_decoder_parse (SwfdecDecoder *dec, SwfdecBuffer *buffer)
   return status;
 }
 
+static SwfdecStatus
+swfdec_swf_decoder_eof (SwfdecDecoder *dec)
+{
+  if (dec->bytes_loaded < dec->bytes_total) {
+    SWFDEC_ERROR ("only %u of %u bytes provided, broken transmission?",
+	dec->bytes_loaded, dec->bytes_total);
+  }
+
+  return 0;
+}
+
 static void
 swfdec_swf_decoder_class_init (SwfdecSwfDecoderClass *class)
 {
@@ -396,6 +407,7 @@ swfdec_swf_decoder_class_init (SwfdecSwfDecoderClass *class)
   object_class->dispose = swfdec_swf_decoder_dispose;
 
   decoder_class->parse = swfdec_swf_decoder_parse;
+  decoder_class->eof = swfdec_swf_decoder_eof;
 }
 
 static void
commit d3da8c049e6bf4f8accb6811ffdf694a3c02f698
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 11:44:44 2007 +0100

    add missing image enum type

diff --git a/test/dump.c b/test/dump.c
index 254a19c..56a270d 100644
--- a/test/dump.c
+++ b/test/dump.c
@@ -316,6 +316,8 @@ get_image_type_name (SwfdecImageType type)
       return "lossless";
     case SWFDEC_IMAGE_TYPE_LOSSLESS2:
       return "lossless with alpha";
+    case SWFDEC_IMAGE_TYPE_PNG:
+      return "PNG";
     case SWFDEC_IMAGE_TYPE_UNKNOWN:
     default:
       g_assert_not_reached ();
commit 961c2949677b75767ee892a6140f41fa812d5c8e
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 12 10:47:33 2007 +0100

    data might be used uninitialized
    
    Also, it's nice to throw an error about unkown formats

diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index 0d0362d..a3094c9 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -448,8 +448,7 @@ swfdec_image_lossless_load (SwfdecImage *image)
 	ptr += 2;
     }
     swfdec_buffer_unref (buffer);
-  }
-  if (format == 5) {
+  } else if (format == 5) {
     SwfdecBuffer *buffer;
     int i, j;
     buffer = swfdec_bits_decompress (&bits, -1, 4 * image->width * image->height);
@@ -471,6 +470,9 @@ swfdec_image_lossless_load (SwfdecImage *image)
     buffer->data = NULL;
     buffer->length = 0;
     swfdec_buffer_unref (buffer);
+  } else {
+    SWFDEC_ERROR ("unknwon lossless image format %u", format);
+    return;
   }
 
 out:
@@ -674,8 +676,8 @@ swfdec_image_new (SwfdecBuffer *buffer)
     goto fail;
   if (buffer->data[0] == 0xFF && buffer->data[1] == 0xD8)
     type = SWFDEC_IMAGE_TYPE_JPEG2;
-  else if (buffer->data[0] == 0xFF && buffer->data[1] == 0xD8 &&
-      buffer->data[0] == 0xFF && buffer->data[1] == 0xD8)
+  else if (buffer->data[0] == 89 && buffer->data[1] == 'P' &&
+      buffer->data[2] == 'N' && buffer->data[3] == 'G')
     type = SWFDEC_IMAGE_TYPE_PNG;
   else
     goto fail;


More information about the Swfdec mailing list