Benjamin Otte
2007-Mar-02 14:33 UTC
[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
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@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@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@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@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@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@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@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@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@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@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@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_@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@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@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
Seemingly Similar Threads
- 3 commits - libswfdec-gtk/swfdec_gtk_loader.c libswfdec/Makefile.am libswfdec/swfdec_codec.c libswfdec/swfdec_codec_ffmpeg.c libswfdec/swfdec_codec_gst.c libswfdec/swfdec_codec.h libswfdec/swfdec_codec_screen.c libswfdec/swfdec_codec_video.c
- 18 commits - doc/swfdec-sections.txt libswfdec/Makefile.am libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_strings.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_event.c libswfdec/swfdec_event.h libswfdec/swfdec_flash_security.c
- configure.ac libswfdec-gtk/swfdec_gtk_widget.c libswfdec-gtk/swfdec_playback_alsa.c libswfdec/swfdec_as_date.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_types.c libswfdec/swfdec_audio_flv.c libswfdec/swfdec_audio_flv.h
- 4 commits - libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_flv_decoder.h libswfdec/swfdec_movie.c test/trace
- 5 commits - libswfdec/jpeg libswfdec/swfdec_as_interpret.c libswfdec/swfdec_bits.c libswfdec/swfdec_cached.c libswfdec/swfdec_codec_adpcm.c libswfdec/swfdec_codec_audio.c libswfdec/swfdec_flash_security.c libswfdec/swfdec_image.c