[Swfdec] 12 commits - libswfdec/Makefile.am libswfdec/swfdec_audio_flv.c libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_js.c libswfdec/swfdec_js.h libswfdec/swfdec_js_video.c libswfdec/swfdec_loader.c libswfdec/swfdec_loader_internal.h libswfdec/swfdec_loadertarget.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_net_stream.h libswfdec/swfdec_player.c libswfdec/swfdec_root_movie.c libswfdec/swfdec_video.c libswfdec/swfdec_video_movie.c libswfdec/swfdec_video_movie.h

Benjamin Otte company at kemper.freedesktop.org
Fri Mar 2 14:33:13 PST 2007


 libswfdec/Makefile.am              |    1 
 libswfdec/swfdec_audio_flv.c       |    4 -
 libswfdec/swfdec_flv_decoder.c     |   60 ++++++++++++++++---
 libswfdec/swfdec_js.c              |    1 
 libswfdec/swfdec_js.h              |    1 
 libswfdec/swfdec_js_video.c        |  114 +++++++++++++++++++++++++++++++++++++
 libswfdec/swfdec_loader.c          |   21 ++++++
 libswfdec/swfdec_loader_internal.h |    1 
 libswfdec/swfdec_loadertarget.c    |   18 ++++-
 libswfdec/swfdec_net_stream.c      |   36 +++++++----
 libswfdec/swfdec_net_stream.h      |    1 
 libswfdec/swfdec_player.c          |    1 
 libswfdec/swfdec_root_movie.c      |   30 +++------
 libswfdec/swfdec_video.c           |   63 ++++++++------------
 libswfdec/swfdec_video_movie.c     |   64 +++++++++++++++-----
 libswfdec/swfdec_video_movie.h     |   21 ++++--
 16 files changed, 333 insertions(+), 104 deletions(-)

New commits:
diff-tree f3b5a7ee8d8516b94c160a3c67dca971ab8065f3 (from e5f35b0679044288cadd72bf14617c145af687ea)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 23:32:56 2007 +0100

    fix video scaling is correct

diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 078ed49..b524725 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -67,15 +67,15 @@ swfdec_net_stream_video_goto (SwfdecNetS
 	    CAIRO_FORMAT_ARGB32, w, h, w * 4);
 	cairo_surface_set_user_data (stream->surface, &key, 
 	    decoded, (cairo_destroy_func_t) swfdec_buffer_unref);
+	if (old != stream->surface) {
+	  GList *walk;
+	  for (walk = stream->movies; walk; walk = walk->next) {
+	    swfdec_video_movie_new_image (walk->data, stream->surface, w, h);
+	  }
+	}
       }
     }
   }
-  if (old != stream->surface) {
-    GList *walk;
-    for (walk = stream->movies; walk; walk = walk->next) {
-      swfdec_video_movie_new_image (walk->data, stream->surface);
-    }
-  }
 }
 
 static void
diff --git a/libswfdec/swfdec_video.c b/libswfdec/swfdec_video.c
index e67be19..bf6b460 100644
--- a/libswfdec/swfdec_video.c
+++ b/libswfdec/swfdec_video.c
@@ -91,7 +91,7 @@ swfdec_video_input_iterate (SwfdecVideoM
       CAIRO_FORMAT_ARGB32, w, h, w * 4);
   cairo_surface_set_user_data (surface, &key, 
       buffer, (cairo_destroy_func_t) swfdec_buffer_unref);
-  swfdec_video_movie_new_image (input->movie, surface);
+  swfdec_video_movie_new_image (input->movie, surface, w, h);
   cairo_surface_destroy (surface);
 }
 
diff --git a/libswfdec/swfdec_video_movie.c b/libswfdec/swfdec_video_movie.c
index 49e1f4d..cf74a92 100644
--- a/libswfdec/swfdec_video_movie.c
+++ b/libswfdec/swfdec_video_movie.c
@@ -46,7 +46,9 @@ swfdec_video_movie_render (SwfdecMovie *
   if (movie->image == NULL)
     return;
 
-  cairo_scale (cr, SWFDEC_TWIPS_SCALE_FACTOR, SWFDEC_TWIPS_SCALE_FACTOR);
+  cairo_scale (cr, 
+      (mov->original_extents.x1 - mov->original_extents.x0) / movie->image_width,
+      (mov->original_extents.y1 - mov->original_extents.y0) / movie->image_height);
   cairo_set_source_surface (cr, movie->image, 0.0, 0.0);
   cairo_paint (cr);
 }
@@ -140,15 +142,20 @@ swfdec_video_movie_clear (SwfdecVideoMov
 }
 
 void
-swfdec_video_movie_new_image (SwfdecVideoMovie *movie, cairo_surface_t *image)
+swfdec_video_movie_new_image (SwfdecVideoMovie *movie, cairo_surface_t *image,
+    guint width, guint height)
 {
   g_return_if_fail (SWFDEC_IS_VIDEO_MOVIE (movie));
   g_return_if_fail (image != NULL);
+  g_return_if_fail (width > 0);
+  g_return_if_fail (height > 0);
 
   if (movie->image)
     cairo_surface_destroy (movie->image);
   cairo_surface_reference (image);
   movie->image = image;
+  movie->image_width = width;
+  movie->image_height = height;
   swfdec_movie_invalidate (SWFDEC_MOVIE (movie));
 }
 
diff --git a/libswfdec/swfdec_video_movie.h b/libswfdec/swfdec_video_movie.h
index 9db5d45..87ee9c9 100644
--- a/libswfdec/swfdec_video_movie.h
+++ b/libswfdec/swfdec_video_movie.h
@@ -54,7 +54,9 @@ struct _SwfdecVideoMovie {
 
   SwfdecVideo *		video;		/* video we play back */
   SwfdecVideoMovieInput *input;		/* where we take the input from */
-  cairo_surface_t *	image;		/* TRUE if cleared */
+  cairo_surface_t *	image;		/* current image or NULL */
+  guint			image_width;	/* width of current image */
+  guint			image_height; 	/* height of current image */
 };
 
 struct _SwfdecVideoMovieClass {
@@ -68,7 +70,9 @@ void		swfdec_video_movie_set_input		(Swf
 void		swfdec_video_movie_clear	      	(SwfdecVideoMovie *	movie);
 /* API for SwfdecVideoMovieInput */
 void		swfdec_video_movie_new_image		(SwfdecVideoMovie *	movie,
-							 cairo_surface_t *	surface);
+							 cairo_surface_t *	surface,
+							 guint			width,
+							 guint			height);
 
 G_END_DECLS
 #endif
diff-tree e5f35b0679044288cadd72bf14617c145af687ea (from 3631478784432ef1912bd12656721d3bbf3cf29f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 22:52:14 2007 +0100

    unref connection and stream after setting them

diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c
index 831641f..da311d4 100644
--- a/libswfdec/swfdec_flv_decoder.c
+++ b/libswfdec/swfdec_flv_decoder.c
@@ -517,6 +517,8 @@ swfdec_flv_decoder_add_movie (SwfdecFlvD
   }
   swfdec_video_movie_set_input (SWFDEC_VIDEO_MOVIE (movie), &stream->input);
   swfdec_net_stream_set_playing (stream, TRUE);
+  g_object_unref (conn);
+  g_object_unref (stream);
 
   return movie;
 }
diff-tree 3631478784432ef1912bd12656721d3bbf3cf29f (from 70509b76bb54d5973f2c01de07a47a9f02f95900)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 22:51:56 2007 +0100

    make swfdec_flv_decoder_get_video/audio more robust
    
    - handle case where there's no audio/video available yet
    - first timestamp will always be 0 in both audio and video streams

diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c
index 31834a2..831641f 100644
--- a/libswfdec/swfdec_flv_decoder.c
+++ b/libswfdec/swfdec_flv_decoder.c
@@ -392,22 +392,33 @@ SwfdecBuffer *
 swfdec_flv_decoder_get_video (SwfdecFlvDecoder *flv, guint timestamp,
     gboolean keyframe, SwfdecVideoFormat *format, guint *real_timestamp, guint *next_timestamp)
 {
-  guint id;
+  guint id, offset;
   SwfdecFlvVideoTag *tag;
 
   g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), NULL);
   g_return_val_if_fail (flv->video != NULL, NULL);
 
+  if (flv->video->len == 0) {
+    if (next_timestamp)
+      *next_timestamp = 0;
+    if (real_timestamp)
+      *real_timestamp = 0;
+    if (format)
+      *format = SWFDEC_VIDEO_FORMAT_UNDEFINED;
+    return NULL;
+  }
+  offset = g_array_index (flv->video, SwfdecFlvVideoTag, 0).timestamp;
+  timestamp += offset;
   id = swfdec_flv_decoder_find_video (flv, timestamp);
   if (next_timestamp) {
     if (id + 1 >= flv->video->len)
       *next_timestamp = 0;
     else
-      *next_timestamp = g_array_index (flv->video, SwfdecFlvVideoTag, id + 1).timestamp;
+      *next_timestamp = g_array_index (flv->video, SwfdecFlvVideoTag, id + 1).timestamp - offset;
   }
   tag = &g_array_index (flv->video, SwfdecFlvVideoTag, id);
   if (real_timestamp)
-    *real_timestamp = tag->timestamp;
+    *real_timestamp = tag->timestamp - offset;
   if (format)
     *format = tag->format;
   return tag->buffer;
@@ -418,22 +429,37 @@ swfdec_flv_decoder_get_audio (SwfdecFlvD
     SwfdecAudioFormat *codec_format, gboolean *width, SwfdecAudioOut *format,
     guint *real_timestamp, guint *next_timestamp)
 {
-  guint id;
+  guint id, offset;
   SwfdecFlvAudioTag *tag;
 
   g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), NULL);
   g_return_val_if_fail (flv->audio != NULL, NULL);
 
+  if (flv->audio->len == 0) {
+    if (next_timestamp)
+      *next_timestamp = 0;
+    if (real_timestamp)
+      *real_timestamp = 0;
+    if (codec_format)
+      *codec_format = SWFDEC_AUDIO_FORMAT_UNDEFINED;
+    if (width)
+      *width = TRUE;
+    if (format)
+      *format = SWFDEC_AUDIO_OUT_STEREO_44100;
+    return NULL;
+  }
+  offset = g_array_index (flv->audio, SwfdecFlvAudioTag, 0).timestamp;
+  timestamp += offset;
   id = swfdec_flv_decoder_find_audio (flv, timestamp);
   if (next_timestamp) {
     if (id + 1 >= flv->audio->len)
       *next_timestamp = 0;
     else
-      *next_timestamp = g_array_index (flv->audio, SwfdecFlvAudioTag, id + 1).timestamp;
+      *next_timestamp = g_array_index (flv->audio, SwfdecFlvAudioTag, id + 1).timestamp - offset;
   }
   tag = &g_array_index (flv->audio, SwfdecFlvAudioTag, id);
   if (real_timestamp)
-    *real_timestamp = tag->timestamp;
+    *real_timestamp = tag->timestamp - offset;
   if (codec_format)
     *codec_format = tag->format;
   if (width)
diff-tree 70509b76bb54d5973f2c01de07a47a9f02f95900 (from b7f4a1999efefba72f607472672ab97f910f32b8)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 22:49:53 2007 +0100

    use swfdec_loader_queue_parse() here, too
    
    - remove leftover g_print debugging
    - fixup stuff that was broken due to missing parsing

diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 4ca99ed..078ed49 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -104,7 +104,6 @@ swfdec_net_stream_update_playing (Swfdec
   should_play &= stream->next_time > stream->current_time;
   if (should_play && stream->timeout.callback == NULL) {
     SWFDEC_DEBUG ("starting playback");
-    g_print ("starting playback\n");
     stream->timeout.callback = swfdec_net_stream_timeout;
     stream->timeout.timestamp = stream->player->time + SWFDEC_MSECS_TO_TICKS (stream->next_time - stream->current_time);
     swfdec_player_add_timeout (stream->player, &stream->timeout);
@@ -116,7 +115,6 @@ swfdec_net_stream_update_playing (Swfdec
       SWFDEC_LOG ("no audio");
     }
   } else if (!should_play && stream->timeout.callback != NULL) {
-    g_print ("stopping playback\n");
     if (stream->audio) {
       SWFDEC_LOG ("stopping audio");
       swfdec_audio_remove (stream->audio);
@@ -147,11 +145,14 @@ static gboolean
 swfdec_net_stream_loader_target_set_decoder (SwfdecLoaderTarget *target,
     SwfdecDecoder *decoder)
 {
+  SwfdecNetStream *stream = SWFDEC_NET_STREAM (target);
+
   if (!SWFDEC_IS_FLV_DECODER (decoder)) {
     g_object_unref (decoder);
     return FALSE;
   }
-  SWFDEC_NET_STREAM (target)->flvdecoder = SWFDEC_FLV_DECODER (decoder);
+  stream->flvdecoder = SWFDEC_FLV_DECODER (decoder);
+  swfdec_net_stream_update_playing (stream);
   return TRUE;
 }
 
@@ -297,6 +298,7 @@ swfdec_net_stream_set_loader (SwfdecNetS
   if (loader) {
     g_object_ref (loader);
     swfdec_loader_set_target (loader, SWFDEC_LOADER_TARGET (stream));
+    swfdec_loader_queue_parse (loader);
   }
   swfdec_net_stream_set_playing (stream, TRUE);
 }
diff-tree b7f4a1999efefba72f607472672ab97f910f32b8 (from 38b78d92441c87d12b7a9c42eb23cb949cd24408)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 22:49:03 2007 +0100

    use swfdec_loader_queue_parse here

diff --git a/libswfdec/swfdec_root_movie.c b/libswfdec/swfdec_root_movie.c
index fb41b82..707f3b4 100644
--- a/libswfdec/swfdec_root_movie.c
+++ b/libswfdec/swfdec_root_movie.c
@@ -170,12 +170,6 @@ swfdec_root_movie_init (SwfdecRootMovie 
 }
 
 void
-swfdec_root_movie_do_parse (gpointer movie, gpointer unused)
-{
-  swfdec_loader_target_parse (SWFDEC_LOADER_TARGET (movie), SWFDEC_ROOT_MOVIE (movie)->loader);
-}
-
-void
 swfdec_root_movie_load (SwfdecRootMovie *root, const char *url, const char *target)
 {
   g_return_if_fail (SWFDEC_IS_ROOT_MOVIE (root));
@@ -196,9 +190,8 @@ swfdec_root_movie_load (SwfdecRootMovie 
       } else {
 	SwfdecLoader *loader = swfdec_loader_load (root->loader, url);
 	if (loader) {
-	  SwfdecRootMovie *added = swfdec_player_add_level_from_loader (root->player, depth, loader, NULL);
-	  swfdec_player_add_action (root->player, SWFDEC_MOVIE (added),
-	      swfdec_root_movie_do_parse, NULL);
+	  swfdec_player_add_level_from_loader (root->player, depth, loader, NULL);
+	  swfdec_loader_queue_parse (loader);
 	} else {
 	  SWFDEC_WARNING ("didn't get a loader for url \"%s\" at depth %u", url, depth);
 	}
diff-tree 38b78d92441c87d12b7a9c42eb23cb949cd24408 (from 896b69f6d5f7211d8d08c9634d66a839c003289f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 22:48:41 2007 +0100

    reset decoder to NULL in error case

diff --git a/libswfdec/swfdec_audio_flv.c b/libswfdec/swfdec_audio_flv.c
index 4544a20..f829fd5 100644
--- a/libswfdec/swfdec_audio_flv.c
+++ b/libswfdec/swfdec_audio_flv.c
@@ -88,8 +88,10 @@ next:
     flv->next_timestamp = soon;
     if (flv->in == 0) {
       /* init */
-      if (flv->decoder)
+      if (flv->decoder) {
 	swfdec_audio_codec_finish (flv->codec, flv->decoder);
+	flv->decoder = NULL;
+      }
       flv->format = format;
       flv->width = width;
       flv->in = in;
diff-tree 896b69f6d5f7211d8d08c9634d66a839c003289f (from e963f3024e9b1e07a381d22defbc9e5da7e31834)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 22:47:48 2007 +0100

    new function swfdec_loader_queue_parse()
    
    use the hack from last commit here

diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c
index 32d0ca4..8a5568f 100644
--- a/libswfdec/swfdec_loader.c
+++ b/libswfdec/swfdec_loader.c
@@ -245,6 +245,27 @@ swfdec_loader_set_target (SwfdecLoader *
   loader->target = target;
 }
 
+static void
+swfdec_loader_do_parse (gpointer empty, gpointer loaderp)
+{
+  SwfdecLoader *loader = SWFDEC_LOADER (loaderp);
+
+  swfdec_loader_target_parse (loader->target, loader);
+}
+
+void
+swfdec_loader_queue_parse (SwfdecLoader *loader)
+{
+  SwfdecPlayer *player;
+
+  g_return_if_fail (SWFDEC_IS_LOADER (loader));
+  g_return_if_fail (loader->target != NULL);
+
+  player = swfdec_loader_target_get_player (loader->target);
+  /* HACK: using player as action object makes them get auto-removed */
+  swfdec_player_add_action (player, player, swfdec_loader_do_parse, loader);
+}
+
 /** PUBLIC API ***/
 
 /**
diff --git a/libswfdec/swfdec_loader_internal.h b/libswfdec/swfdec_loader_internal.h
index 3c99959..7d5aaef 100644
--- a/libswfdec/swfdec_loader_internal.h
+++ b/libswfdec/swfdec_loader_internal.h
@@ -29,6 +29,7 @@ G_BEGIN_DECLS
 SwfdecLoader *		swfdec_loader_load		(SwfdecLoader *		loader,
 							 const char *		url);
 void			swfdec_loader_parse		(SwfdecLoader *		loader);
+void			swfdec_loader_queue_parse	(SwfdecLoader *		loader);
 void			swfdec_loader_set_target	(SwfdecLoader *		loader,
 							 SwfdecLoaderTarget *	target);
 void	  		swfdec_loader_error_locked	(SwfdecLoader *		loader,
diff-tree e963f3024e9b1e07a381d22defbc9e5da7e31834 (from f39596ffc3e8d4f72da538f822f174390bbdf751)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 22:47:25 2007 +0100

    Add a hack to allow adding actions that get executed "no matter what"

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 6de320b..81d06fa 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -358,6 +358,7 @@ swfdec_player_dispose (GObject *object)
 
   swfdec_js_finish_player (player);
 
+  swfdec_player_remove_all_actions (player, player); /* HACK to allow non-removable actions */
   g_assert (swfdec_ring_buffer_pop (player->actions) == NULL);
   swfdec_ring_buffer_free (player->actions);
   g_assert (player->movies == NULL);
diff-tree f39596ffc3e8d4f72da538f822f174390bbdf751 (from b0cf46e2bf75776ea6c5729c6996d8924c13e126)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 21:04:34 2007 +0100

    fix how we handle FLV streams so it works with modified SwfdecLoaderTarget
    
    It's still a huge hack

diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c
index b5640f7..31834a2 100644
--- a/libswfdec/swfdec_flv_decoder.c
+++ b/libswfdec/swfdec_flv_decoder.c
@@ -452,6 +452,17 @@ swfdec_flv_decoder_get_audio (SwfdecFlvD
 #include "swfdec_root_movie.h"
 #include "swfdec_sprite.h"
 #include "swfdec_video_movie.h"
+
+static void
+notify_initialized (SwfdecPlayer *player, GParamSpec *pspec, SwfdecVideoMovie *movie)
+{
+  movie->video->width = player->width;
+  movie->video->height = player->height;
+
+  swfdec_movie_queue_update (SWFDEC_MOVIE (movie), SWFDEC_MOVIE_INVALID_MATRIX);
+  swfdec_movie_invalidate (SWFDEC_MOVIE (movie));
+}
+
 SwfdecMovie *
 swfdec_flv_decoder_add_movie (SwfdecFlvDecoder *flv, SwfdecMovie *parent)
 {
@@ -463,18 +474,19 @@ swfdec_flv_decoder_add_movie (SwfdecFlvD
 
   /* set up the video movie */
   video = g_object_new (SWFDEC_TYPE_VIDEO, NULL);
-  video->width = SWFDEC_DECODER (flv)->width;
-  video->height = SWFDEC_DECODER (flv)->height;
+  video->width = G_MAXUINT;
+  video->height = G_MAXUINT;
   content->graphic = SWFDEC_GRAPHIC (video);
   movie = swfdec_movie_new (parent, content);
   g_object_weak_ref (G_OBJECT (movie), (GWeakNotify) swfdec_content_free, content);
   g_object_weak_ref (G_OBJECT (movie), (GWeakNotify) g_object_unref, video);
+  g_signal_connect (SWFDEC_ROOT_MOVIE (parent)->player, "notify::initialized",
+      G_CALLBACK (notify_initialized), movie);
   /* set up the playback stream */
   conn = swfdec_connection_new (SWFDEC_ROOT_MOVIE (parent)->player->jscx);
   stream = swfdec_net_stream_new (SWFDEC_ROOT_MOVIE (parent)->player, conn);
   swfdec_net_stream_set_loader (stream, SWFDEC_ROOT_MOVIE (parent)->loader);
-  g_object_ref (SWFDEC_ROOT_MOVIE (parent)->decoder);
-  if (!swfdec_loader_target_set_decoder (SWFDEC_LOADER_TARGET (stream), SWFDEC_ROOT_MOVIE (parent)->decoder)) {
+  if (!swfdec_loader_target_set_decoder (SWFDEC_LOADER_TARGET (stream), SWFDEC_DECODER (flv))) {
     g_assert_not_reached ();
   }
   swfdec_video_movie_set_input (SWFDEC_VIDEO_MOVIE (movie), &stream->input);
diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index 2a0b897..4ca99ed 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -34,7 +34,7 @@ swfdec_net_stream_video_goto (SwfdecNetS
   SwfdecVideoFormat format;
   cairo_surface_t *old;
 
-  SWFDEC_LOG ("goto %ums\n", timestamp);
+  SWFDEC_LOG ("goto %ums", timestamp);
   buffer = swfdec_flv_decoder_get_video (stream->flvdecoder, timestamp,
       FALSE, &format, &stream->current_time, &stream->next_time);
   old = stream->surface;
@@ -104,6 +104,7 @@ swfdec_net_stream_update_playing (Swfdec
   should_play &= stream->next_time > stream->current_time;
   if (should_play && stream->timeout.callback == NULL) {
     SWFDEC_DEBUG ("starting playback");
+    g_print ("starting playback\n");
     stream->timeout.callback = swfdec_net_stream_timeout;
     stream->timeout.timestamp = stream->player->time + SWFDEC_MSECS_TO_TICKS (stream->next_time - stream->current_time);
     swfdec_player_add_timeout (stream->player, &stream->timeout);
@@ -115,6 +116,7 @@ swfdec_net_stream_update_playing (Swfdec
       SWFDEC_LOG ("no audio");
     }
   } else if (!should_play && stream->timeout.callback != NULL) {
+    g_print ("stopping playback\n");
     if (stream->audio) {
       SWFDEC_LOG ("stopping audio");
       swfdec_audio_remove (stream->audio);
@@ -285,9 +287,8 @@ swfdec_net_stream_set_loader (SwfdecNetS
   g_return_if_fail (SWFDEC_IS_NET_STREAM (stream));
   g_return_if_fail (loader == NULL || SWFDEC_IS_LOADER (loader));
 
-  if (stream->loader) {
+  if (stream->loader)
     g_object_unref (stream->loader);
-  }
   if (stream->flvdecoder) {
     g_object_unref (stream->flvdecoder);
     stream->flvdecoder = NULL;
diff --git a/libswfdec/swfdec_root_movie.c b/libswfdec/swfdec_root_movie.c
index 1b7c264..fb41b82 100644
--- a/libswfdec/swfdec_root_movie.c
+++ b/libswfdec/swfdec_root_movie.c
@@ -57,7 +57,15 @@ static gboolean
 swfdec_root_movie_loader_target_set_decoder (SwfdecLoaderTarget *target,
     SwfdecDecoder *decoder)
 {
-  SWFDEC_ROOT_MOVIE (target)->decoder = decoder;
+  if (SWFDEC_IS_FLV_DECODER (decoder)) {
+    swfdec_flv_decoder_add_movie (SWFDEC_FLV_DECODER (decoder), 
+	SWFDEC_MOVIE (target));
+  } else if (SWFDEC_IS_SWF_DECODER (decoder)) {
+    SWFDEC_ROOT_MOVIE (target)->decoder = decoder;
+  } else {
+    g_object_unref (decoder);
+    return FALSE;
+  }
   return TRUE;
 }
 
@@ -66,19 +74,12 @@ swfdec_root_movie_loader_target_do_init 
 {
   SwfdecRootMovie *movie = SWFDEC_ROOT_MOVIE (target);
 
-  swfdec_player_initialize (movie->player, movie->decoder->rate, 
-      movie->decoder->width, movie->decoder->height);
-  if (SWFDEC_IS_SWF_DECODER (movie->decoder) &&
-      movie->player->roots->next == 0) { 
+  if (movie->player->roots->next == 0) { 
     /* if we're the only child */
     /* FIXME: check case sensitivity wrt embedding movies of different version */
     JS_SetContextCaseSensitive (movie->player->jscx,
 	SWFDEC_SWF_DECODER (movie->decoder)->version > 6);
   }
-  if (SWFDEC_IS_FLV_DECODER (movie->decoder)) {
-    swfdec_flv_decoder_add_movie (SWFDEC_FLV_DECODER (movie->decoder), 
-	SWFDEC_MOVIE (movie));
-  }
   return TRUE;
 }
 
diff-tree b0cf46e2bf75776ea6c5729c6996d8924c13e126 (from 6999042e149d403d64d3f16126d9840518a5afc7)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 21:01:18 2007 +0100

    fix default parser
    
    - reread target after setting the decoder, the target might change
    - initialize player when decoder returns INIT

diff --git a/libswfdec/swfdec_loadertarget.c b/libswfdec/swfdec_loadertarget.c
index 6af5504..5a25f1a 100644
--- a/libswfdec/swfdec_loadertarget.c
+++ b/libswfdec/swfdec_loadertarget.c
@@ -23,6 +23,7 @@
 
 #include "swfdec_loadertarget.h"
 #include "swfdec_loader_internal.h"
+#include "swfdec_player_internal.h"
 
 static void
 swfdec_loader_target_base_init (gpointer g_class)
@@ -95,6 +96,7 @@ swfdec_loader_target_parse_default (Swfd
       swfdec_loader_error_locked (loader, "Internal error");
       return;
     }
+    target = loader->target;
   }
   klass = SWFDEC_DECODER_GET_CLASS (dec);
   g_return_if_fail (klass->parse);
@@ -115,11 +117,17 @@ swfdec_loader_target_parse_default (Swfd
 	}
 	break;
       case SWFDEC_STATUS_INIT:
-	g_assert (dec->width > 0);
-	g_assert (dec->height > 0);
-	if (!swfdec_loader_target_init (target)) {
-	  swfdec_loader_error_locked (loader, "Internal error");
-	  return;
+	{
+	  SwfdecPlayer *player;
+	  player = swfdec_loader_target_get_player (target);
+	  g_assert (dec->width > 0);
+	  g_assert (dec->height > 0);
+	  swfdec_player_initialize (player, dec->rate, 
+	      dec->width, dec->height);
+	  if (!swfdec_loader_target_init (target)) {
+	    swfdec_loader_error_locked (loader, "Internal error");
+	    return;
+	  }
 	}
 	break;
       case SWFDEC_STATUS_EOF:
diff-tree 6999042e149d403d64d3f16126d9840518a5afc7 (from de1c2f0273dadc8e74161d157511bb0b6b59d823)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 09:57:14 2007 +0100

    add Video class

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 68cdbbf..cce0bbc 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -54,6 +54,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_js_movie.c \
 	swfdec_js_net_stream.c \
 	swfdec_js_sound.c \
+	swfdec_js_video.c \
 	swfdec_js_xml.c \
 	swfdec_listener.c \
 	swfdec_loader.c \
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index e26e33d..ce68144 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -112,6 +112,7 @@ swfdec_js_init_player (SwfdecPlayer *pla
   swfdec_js_add_movieclip_class (player);
   swfdec_js_add_color (player);
   swfdec_js_add_sound (player);
+  swfdec_js_add_video (player);
   swfdec_js_add_xml (player);
   swfdec_js_add_connection (player);
   swfdec_js_add_net_stream (player);
diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h
index 6c5b804..f32374b 100644
--- a/libswfdec/swfdec_js.h
+++ b/libswfdec/swfdec_js.h
@@ -44,6 +44,7 @@ void		swfdec_js_add_mouse		(SwfdecPlayer
 void		swfdec_js_add_movieclip_class	(SwfdecPlayer *		player);
 void		swfdec_js_add_net_stream	(SwfdecPlayer *		player);
 void		swfdec_js_add_sound		(SwfdecPlayer *		player);
+void		swfdec_js_add_video		(SwfdecPlayer *		player);
 void		swfdec_js_add_xml		(SwfdecPlayer *		player);
 
 void		swfdec_js_movie_add_property	(SwfdecMovie *		movie);
diff --git a/libswfdec/swfdec_js_video.c b/libswfdec/swfdec_js_video.c
new file mode 100644
index 0000000..db2e64f
--- /dev/null
+++ b/libswfdec/swfdec_js_video.c
@@ -0,0 +1,114 @@
+/* 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_video.h"
+#include "swfdec_debug.h"
+#include "swfdec_js.h"
+#include "swfdec_net_stream.h"
+#include "swfdec_player_internal.h"
+
+static JSBool
+swfdec_js_video_attach_video (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecNetStream *stream;
+  SwfdecVideoMovie *video;
+
+  video = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_VIDEO_MOVIE);
+  if (video == NULL)
+    return JS_TRUE;
+
+  stream = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_NET_STREAM);
+  if (stream != NULL) {
+    swfdec_video_movie_set_input (video, &stream->input);
+    return JS_TRUE;
+  }
+  swfdec_video_movie_set_input (video, NULL);
+  return JS_TRUE;
+}
+
+static JSBool
+swfdec_js_video_clear (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  SwfdecVideoMovie *video;
+
+  video = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_VIDEO_MOVIE);
+  if (video == NULL)
+    return JS_TRUE;
+
+  swfdec_video_movie_clear (video);
+  return JS_TRUE;
+}
+
+static JSBool
+swfdec_js_video_to_string (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  JSString *string;
+
+  string = JS_InternString (cx, "[object Object]");
+  if (string == NULL)
+    return JS_FALSE;
+
+  *rval = STRING_TO_JSVAL (string);
+  return JS_TRUE;
+}
+
+static JSFunctionSpec video_methods[] = {
+  { "attachVideo",    	swfdec_js_video_attach_video,	1, 0, 0 },
+  { "clear",    	swfdec_js_video_clear,		0, 0, 0 },
+  { "toString",		swfdec_js_video_to_string,	0, 0, 0 },
+  {0,0,0,0,0}
+};
+
+static void
+swfdec_js_video_finalize (JSContext *cx, JSObject *obj)
+{
+  SwfdecVideo *video;
+
+  video = JS_GetPrivate (cx, obj);
+  if (video) {
+    SWFDEC_SCRIPTABLE (video)->jsobj = NULL;
+    g_object_unref (video);
+  }
+}
+
+const JSClass video_class = {
+    "Video", JSCLASS_HAS_PRIVATE,
+    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
+    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   swfdec_js_video_finalize,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+swfdec_js_video_new (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  return JS_TRUE;
+}
+
+void
+swfdec_js_add_video (SwfdecPlayer *player)
+{
+  JS_InitClass (player->jscx, player->jsobj, NULL,
+      &video_class, swfdec_js_video_new, 0, NULL, video_methods,
+      NULL, NULL);
+}
+
diff-tree de1c2f0273dadc8e74161d157511bb0b6b59d823 (from 7e865ad995f10d135ac60a20d725fb81e5c68372)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Mar 2 09:56:56 2007 +0100

    rework video embedding API
    
    It now only has the functions connect() and disconnect()

diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c
index b6f15e8..2a0b897 100644
--- a/libswfdec/swfdec_net_stream.c
+++ b/libswfdec/swfdec_net_stream.c
@@ -32,10 +32,12 @@ swfdec_net_stream_video_goto (SwfdecNetS
 {
   SwfdecBuffer *buffer;
   SwfdecVideoFormat format;
+  cairo_surface_t *old;
 
   SWFDEC_LOG ("goto %ums\n", timestamp);
   buffer = swfdec_flv_decoder_get_video (stream->flvdecoder, timestamp,
       FALSE, &format, &stream->current_time, &stream->next_time);
+  old = stream->surface;
   if (stream->surface) {
     cairo_surface_destroy (stream->surface);
     stream->surface = NULL;
@@ -68,8 +70,12 @@ swfdec_net_stream_video_goto (SwfdecNetS
       }
     }
   }
-  if (stream->input.movie)
-    swfdec_movie_invalidate (SWFDEC_MOVIE (stream->input.movie));
+  if (old != stream->surface) {
+    GList *walk;
+    for (walk = stream->movies; walk; walk = walk->next) {
+      swfdec_video_movie_new_image (walk->data, stream->surface);
+    }
+  }
 }
 
 static void
@@ -182,19 +188,21 @@ swfdec_net_stream_loader_target_init (Sw
 
 /*** SWFDEC VIDEO MOVIE INPUT ***/
 
-static cairo_surface_t *
-swfdec_net_stream_input_get_image (SwfdecVideoMovieInput *input)
+static void
+swfdec_net_stream_input_connect (SwfdecVideoMovieInput *input, SwfdecVideoMovie *movie)
 {
   SwfdecNetStream *stream = SWFDEC_NET_STREAM ((guchar *) input - G_STRUCT_OFFSET (SwfdecNetStream, input));
 
-  return stream->surface;
+  stream->movies = g_list_prepend (stream->movies, movie);
+  g_object_ref (stream);
 }
 
 static void
-swfdec_net_stream_input_finalize (SwfdecVideoMovieInput *input)
+swfdec_net_stream_input_disconnect (SwfdecVideoMovieInput *input, SwfdecVideoMovie *movie)
 {
   SwfdecNetStream *stream = SWFDEC_NET_STREAM ((guchar *) input - G_STRUCT_OFFSET (SwfdecNetStream, input));
 
+  stream->movies = g_list_remove (stream->movies, movie);
   g_object_unref (stream);
 }
 
@@ -218,6 +226,7 @@ swfdec_net_stream_dispose (GObject *obje
   swfdec_net_stream_set_loader (stream, NULL);
   g_object_unref (stream->conn);
   stream->conn = NULL;
+  g_assert (stream->movies == NULL);
 
   G_OBJECT_CLASS (swfdec_net_stream_parent_class)->dispose (object);
 }
@@ -237,8 +246,8 @@ swfdec_net_stream_class_init (SwfdecNetS
 static void
 swfdec_net_stream_init (SwfdecNetStream *stream)
 {
-  stream->input.get_image = swfdec_net_stream_input_get_image;
-  stream->input.finalize = swfdec_net_stream_input_finalize;
+  stream->input.connect = swfdec_net_stream_input_connect;
+  stream->input.disconnect = swfdec_net_stream_input_disconnect;
 }
 
 SwfdecNetStream *
diff --git a/libswfdec/swfdec_net_stream.h b/libswfdec/swfdec_net_stream.h
index 012a11d..ce22330 100644
--- a/libswfdec/swfdec_net_stream.h
+++ b/libswfdec/swfdec_net_stream.h
@@ -59,6 +59,7 @@ struct _SwfdecNetStream
   cairo_surface_t *	surface;	/* current image */
   SwfdecTimeout		timeout;	/* timeout to advance to */
   SwfdecVideoMovieInput	input;		/* used when attaching to a video movie */
+  GList *		movies;		/* movies we're connected to */
 
   /* audio */
   SwfdecAudio *		audio;		/* audio stream or NULL when not playing */
diff --git a/libswfdec/swfdec_video.c b/libswfdec/swfdec_video.c
index 867259c..e67be19 100644
--- a/libswfdec/swfdec_video.c
+++ b/libswfdec/swfdec_video.c
@@ -59,26 +59,20 @@ swfdec_video_find_frame (SwfdecVideo *vi
 
 typedef struct {
   SwfdecVideoMovieInput	input;
+  SwfdecVideoMovie *	movie;
   SwfdecVideo *		video;
   gpointer		decoder;
   guint			current_frame;
-  SwfdecBuffer *	current_buffer;
-  cairo_surface_t *	surface;
 } SwfdecVideoInput;
 
-static cairo_surface_t *
-swfdec_video_input_get_image (SwfdecVideoMovieInput *input_)
-{
-  SwfdecVideoInput *input = (SwfdecVideoInput *) input_;
-
-  return input->surface;
-}
-
 static void
 swfdec_video_input_iterate (SwfdecVideoMovieInput *input_)
 {
   SwfdecVideoInput *input = (SwfdecVideoInput *) input_;
   SwfdecBuffer *buffer;
+  static const cairo_user_data_key_t key;
+  guint w, h;
+  cairo_surface_t *surface;
 
   input->current_frame = (input->current_frame + 1) % input->video->n_frames;
   if (input->decoder == NULL)
@@ -87,38 +81,35 @@ swfdec_video_input_iterate (SwfdecVideoM
   if (buffer == NULL)
     return;
 
-  if (input->current_buffer != NULL) {
-    swfdec_buffer_unref (input->current_buffer);
-    cairo_surface_destroy (input->surface);
-  }
-  input->current_buffer = swfdec_video_codec_decode (input->video->codec, 
-      input->decoder, buffer);
-  if (input->current_buffer) {
-    guint w, h;
-    if (swfdec_video_codec_get_size (input->video->codec,
-	  input->decoder, &w, &h)) {
-      input->surface = cairo_image_surface_create_for_data (
-	  input->current_buffer->data, CAIRO_FORMAT_ARGB32,
-	  w, h, w * 4);
-    } else {
-      /* if we get a buffer, the decoder must be able to tell us its size */
+  buffer = swfdec_video_codec_decode (input->video->codec, input->decoder, buffer);
+  if (buffer == NULL)
+    return;
+  if (!swfdec_video_codec_get_size (input->video->codec, input->decoder, &w, &h)) {
       g_assert_not_reached ();
-    }
-  } else {
-    input->surface = NULL;
   }
-  swfdec_movie_invalidate (SWFDEC_MOVIE (input->input.movie));
+  surface = cairo_image_surface_create_for_data (buffer->data, 
+      CAIRO_FORMAT_ARGB32, w, h, w * 4);
+  cairo_surface_set_user_data (surface, &key, 
+      buffer, (cairo_destroy_func_t) swfdec_buffer_unref);
+  swfdec_video_movie_new_image (input->movie, surface);
+  cairo_surface_destroy (surface);
 }
 
 static void
-swfdec_video_input_finalize (SwfdecVideoMovieInput *input_)
+swfdec_video_input_connect (SwfdecVideoMovieInput *input_, SwfdecVideoMovie *movie)
 {
   SwfdecVideoInput *input = (SwfdecVideoInput *) input_;
 
-  if (input->current_buffer != NULL) {
-    swfdec_buffer_unref (input->current_buffer);
-    cairo_surface_destroy (input->surface);
-  }
+  g_assert (input->movie == NULL);
+  input->movie = movie;
+}
+
+static void
+swfdec_video_input_disconnect (SwfdecVideoMovieInput *input_, SwfdecVideoMovie *movie)
+{
+  SwfdecVideoInput *input = (SwfdecVideoInput *) input_;
+
+  g_assert (input->movie == movie);
   if (input->decoder)
     swfdec_video_codec_finish (input->video->codec, input->decoder);
   g_object_unref (input->video);
@@ -138,9 +129,9 @@ swfdec_video_input_new (SwfdecVideo *vid
     input->decoder = swfdec_video_codec_init (video->codec);
   if (input->decoder == NULL)
     return NULL;
-  input->input.get_image = swfdec_video_input_get_image;
+  input->input.connect = swfdec_video_input_connect;
   input->input.iterate = swfdec_video_input_iterate;
-  input->input.finalize = swfdec_video_input_finalize;
+  input->input.disconnect = swfdec_video_input_disconnect;
   g_object_ref (video);
   input->video = video;
   input->current_frame = (guint) -1;
diff --git a/libswfdec/swfdec_video_movie.c b/libswfdec/swfdec_video_movie.c
index dc7e9ec..49e1f4d 100644
--- a/libswfdec/swfdec_video_movie.c
+++ b/libswfdec/swfdec_video_movie.c
@@ -42,21 +42,13 @@ swfdec_video_movie_render (SwfdecMovie *
     const SwfdecColorTransform *trans, const SwfdecRect *inval, gboolean fill)
 {
   SwfdecVideoMovie *movie = SWFDEC_VIDEO_MOVIE (mov);
-  cairo_surface_t *surface;
 
-  if (movie->input == NULL)
+  if (movie->image == NULL)
     return;
 
-  surface = movie->input->get_image (movie->input);
   cairo_scale (cr, SWFDEC_TWIPS_SCALE_FACTOR, SWFDEC_TWIPS_SCALE_FACTOR);
-  if (surface != NULL) {
-    cairo_set_source_surface (cr, surface, 0.0, 0.0);
-    cairo_paint (cr);
-  } else {
-    cairo_set_source_rgb (cr, 0, 0, 0);
-    cairo_rectangle (cr, 0, 0, movie->video->width, movie->video->height);
-    cairo_fill (cr);
-  }
+  cairo_set_source_surface (cr, movie->image, 0.0, 0.0);
+  cairo_paint (cr);
 }
 
 static void
@@ -65,8 +57,8 @@ swfdec_video_movie_unset_input (SwfdecVi
   if (movie->input == NULL)
     return;
 
-  if (movie->input->finalize)
-    movie->input->finalize (movie->input);
+  if (movie->input->disconnect)
+    movie->input->disconnect (movie->input, movie);
   movie->input = NULL;
 }
 
@@ -76,6 +68,10 @@ swfdec_video_movie_dispose (GObject *obj
   SwfdecVideoMovie *movie = SWFDEC_VIDEO_MOVIE (object);
 
   swfdec_video_movie_unset_input (movie);
+  if (movie->image) {
+    cairo_surface_destroy (movie->image);
+    movie->image = NULL;
+  }
   g_object_unref (movie->video);
 
   G_OBJECT_CLASS (swfdec_video_movie_parent_class)->dispose (object);
@@ -96,14 +92,18 @@ swfdec_video_movie_iterate_end (SwfdecMo
   return TRUE;
 }
 
+extern const JSClass video_class;
 static void
 swfdec_video_movie_class_init (SwfdecVideoMovieClass * g_class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (g_class);
+  SwfdecScriptableClass *scriptable_class = SWFDEC_SCRIPTABLE_CLASS (g_class);
   SwfdecMovieClass *movie_class = SWFDEC_MOVIE_CLASS (g_class);
 
   object_class->dispose = swfdec_video_movie_dispose;
 
+  scriptable_class->jsclass = &video_class;
+
   movie_class->update_extents = swfdec_video_movie_update_extents;
   movie_class->render = swfdec_video_movie_render;
   movie_class->iterate_end = swfdec_video_movie_iterate_end;
@@ -119,11 +119,36 @@ swfdec_video_movie_set_input (SwfdecVide
 {
   g_return_if_fail (SWFDEC_IS_VIDEO_MOVIE (movie));
   g_return_if_fail (input != NULL);
-  g_return_if_fail (input->get_image);
 
   swfdec_video_movie_unset_input (movie);
   movie->input = input;
-  input->movie = movie;
+  if (input->connect)
+    input->connect (input, movie);
+}
+
+void
+swfdec_video_movie_clear (SwfdecVideoMovie *movie)
+{
+  g_return_if_fail (SWFDEC_IS_VIDEO_MOVIE (movie));
+
+  if (movie->image == NULL)
+    return;
+
+  cairo_surface_destroy (movie->image);
+  movie->image = NULL;
+  swfdec_movie_invalidate (SWFDEC_MOVIE (movie));
+}
+
+void
+swfdec_video_movie_new_image (SwfdecVideoMovie *movie, cairo_surface_t *image)
+{
+  g_return_if_fail (SWFDEC_IS_VIDEO_MOVIE (movie));
+  g_return_if_fail (image != NULL);
+
+  if (movie->image)
+    cairo_surface_destroy (movie->image);
+  cairo_surface_reference (image);
+  movie->image = image;
   swfdec_movie_invalidate (SWFDEC_MOVIE (movie));
 }
 
diff --git a/libswfdec/swfdec_video_movie.h b/libswfdec/swfdec_video_movie.h
index 7708c37..9db5d45 100644
--- a/libswfdec/swfdec_video_movie.h
+++ b/libswfdec/swfdec_video_movie.h
@@ -39,14 +39,14 @@ typedef struct _SwfdecVideoMovieInput Sw
 
 /* FIXME: make an interface? */
 struct _SwfdecVideoMovieInput {
-  /* get surface holding current image or NULL to use black */
-  cairo_surface_t *	(* get_image)	(SwfdecVideoMovieInput *input);
+  /* connect to movie */
+  void			(* connect)	(SwfdecVideoMovieInput *input,
+					 SwfdecVideoMovie *	movie);
+  /* called when input is unset */
+  void			(* disconnect)	(SwfdecVideoMovieInput *input,
+					 SwfdecVideoMovie *	movie);
   /* called when movie is iterating */
   void			(* iterate)	(SwfdecVideoMovieInput *input);
-  /* called when input is unset */
-  void			(* finalize)	(SwfdecVideoMovieInput *input);
-  /* set by movie */
-  SwfdecVideoMovie *	movie;
 };
 
 struct _SwfdecVideoMovie {
@@ -54,6 +54,7 @@ struct _SwfdecVideoMovie {
 
   SwfdecVideo *		video;		/* video we play back */
   SwfdecVideoMovieInput *input;		/* where we take the input from */
+  cairo_surface_t *	image;		/* TRUE if cleared */
 };
 
 struct _SwfdecVideoMovieClass {
@@ -64,6 +65,10 @@ GType		swfdec_video_movie_get_type		(voi
 
 void		swfdec_video_movie_set_input		(SwfdecVideoMovie *	movie,
 							 SwfdecVideoMovieInput *input);
+void		swfdec_video_movie_clear	      	(SwfdecVideoMovie *	movie);
+/* API for SwfdecVideoMovieInput */
+void		swfdec_video_movie_new_image		(SwfdecVideoMovie *	movie,
+							 cairo_surface_t *	surface);
 
 G_END_DECLS
 #endif


More information about the Swfdec mailing list