Benjamin Otte
2007-Mar-14 13:12 UTC
[Swfdec] 10 commits - libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_flv_decoder.h libswfdec/swfdec_js_global.c libswfdec/swfdec_js_movie.c libswfdec/swfdec_js_net_stream.c libswfdec/swfdec_loader.c libswfdec/swfdec_loader.h libswfdec/swfdec_loadertarget.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_net_stream.h test/trace
libswfdec/swfdec_flv_decoder.c | 43 +++++ libswfdec/swfdec_flv_decoder.h | 10 + libswfdec/swfdec_js_global.c | 2 libswfdec/swfdec_js_movie.c | 3 libswfdec/swfdec_js_net_stream.c | 18 ++ libswfdec/swfdec_loader.c | 44 +++-- libswfdec/swfdec_loader.h | 2 libswfdec/swfdec_loadertarget.c | 8 - libswfdec/swfdec_net_stream.c | 184 +++++++++++++++++------ libswfdec/swfdec_net_stream.h | 7 test/trace/Makefile.am | 10 + test/trace/README | 40 +++-- test/trace/netstream-onstatus-notfound.as | 14 + test/trace/netstream-onstatus-notfound.swf |binary test/trace/netstream-onstatus-notfound.swf.trace | 6 test/trace/netstream-onstatus.c | 44 +++++ test/trace/netstream-onstatus.swf |binary test/trace/netstream-onstatus.swf.trace | 12 + test/trace/setinterval-arguments.as | 4 test/trace/setinterval-arguments.swf |binary test/trace/setinterval-arguments.swf.trace | 4 test/trace/trace.c | 15 + test/trace/video.flv |binary 23 files changed, 383 insertions(+), 87 deletions(-) New commits: diff-tree dedf24e3a36c463b0fa40d83e5b80ff36024baa3 (from 10dd6dc219da2fa309574ecc7e8cbf266aa1433b) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 20:35:37 2007 +0100 update the README to include information about source files diff --git a/test/trace/README b/test/trace/README index f6ae935..730ec0c 100644 --- a/test/trace/README +++ b/test/trace/README @@ -14,6 +14,23 @@ written to a file named "tmp". The retur failure if at least one test failed. +What are all the other files? + +Some test files are created with Open Source tools. In that case, the sources +used for creating them are included and named $FILE.$TOOL-EXTENSION. Every +one of those files includes the command that were used for creating the test +files. + + +Why don't you autogenerate the SWF files from sources but include them? + +An important thing to note is that this testsuite is supposed to test the +correct handling of SWF files, so the reference file must be an SWF file. Since +Open Source tools could produce different SWF files depending on version, we +the testsuite could end up testing different files. This is something that is +definitely not wanted. Consider the source files annotations only. + + How do I run my new test? Create a file to test, say "test.swf", and put the expected output in the @@ -33,7 +50,8 @@ Unfortunately this requires access to th How do I add a test to the testsuite? -Just put the file and its trace file into this directory and add both to -EXTRA_DIST in Makefile.am. It should appear in the output when running -make check. (Note that the order of files tested during make check is pretty -much random.) +Just put the file, its trace file and if you have them, source files used for +creating the file into this directory and add all of them to EXTRA_DIST in +Makefile.am. The file should appear in the output when running make check. +(Note that the order of files tested during make check is pretty much random.) + diff-tree 10dd6dc219da2fa309574ecc7e8cbf266aa1433b (from 2f64500b40e8735c34ff65811ff8661f59621a22) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 20:27:13 2007 +0100 add 2 tests for onStatus messages This includes a video only FLV file for use in tests including video. Please reuse it. diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am index 3b50bae..20e4684 100644 --- a/test/trace/Makefile.am +++ b/test/trace/Makefile.am @@ -113,6 +113,12 @@ EXTRA_DIST = \ names.swf.trace \ netconnection.swf \ netconnection.swf.trace \ + netstream-onstatus.c \ + netstream-onstatus.swf \ + netstream-onstatus.trace \ + netstream-onstatus-notfound.as \ + netstream-onstatus-notfound.swf \ + netstream-onstatus-notfound.swf.trace \ number.swf \ number.swf.trace \ object-math-5.swf \ @@ -161,6 +167,7 @@ EXTRA_DIST = \ undefined2-6.swf.trace \ undefined2-7.swf \ undefined2-7.swf.trace \ + video.flv \ xscale.swf \ xscale.swf.trace diff --git a/test/trace/netstream-onstatus-notfound.as b/test/trace/netstream-onstatus-notfound.as new file mode 100644 index 0000000..1cd5983 --- /dev/null +++ b/test/trace/netstream-onstatus-notfound.as @@ -0,0 +1,14 @@ +// makeswf -v 7 -s 200x150 -r 1 -o netstream-onstatus-notfound.swf netstream-onstatus-notfound.as + +trace ("Test onStatus emission for nonexisting movies"); +nc = new NetConnection (); +nc.connect (null); +ns = new NetStream (nc); +ns.onStatus = function (info) { + trace ("NetStream onStatus called"); + trace (info.code); + trace (info.level); +}; +trace ("Calling play"); +ns.play ("doesnotexist.flv"); +trace ("done calling play"); diff --git a/test/trace/netstream-onstatus-notfound.swf b/test/trace/netstream-onstatus-notfound.swf new file mode 100644 index 0000000..ecdd844 Binary files /dev/null and b/test/trace/netstream-onstatus-notfound.swf differ diff --git a/test/trace/netstream-onstatus-notfound.swf.trace b/test/trace/netstream-onstatus-notfound.swf.trace new file mode 100644 index 0000000..d24b102 --- /dev/null +++ b/test/trace/netstream-onstatus-notfound.swf.trace @@ -0,0 +1,6 @@ +Test onStatus emission for nonexisting movies +Calling play +done calling play +NetStream onStatus called +NetStream.Play.StreamNotFound +error diff --git a/test/trace/netstream-onstatus.c b/test/trace/netstream-onstatus.c new file mode 100644 index 0000000..37c4ad5 --- /dev/null +++ b/test/trace/netstream-onstatus.c @@ -0,0 +1,44 @@ +/* gcc `pkg-config --libs --cflags libming` netstream-onstatus.c -o netstream-onstatus && ./netstream-onstatus + */ + +#include <ming.h> + +int +main (int argc, char **argv) +{ + SWFMovie movie; + SWFVideoStream video; + SWFDisplayItem item; + SWFAction action; + + if (Ming_init ()) + return 1; + Ming_useSWFVersion (7); + + movie = newSWFMovie(); + SWFMovie_setRate (movie, 1); + SWFMovie_setDimension (movie, 200, 150); + video = newSWFVideoStream (); + SWFVideoStream_setDimension (video, 200, 150); + item = SWFMovie_add (movie, (SWFBlock) video); + SWFDisplayItem_setName (item, "video"); + action = compileSWFActionCode ("" + "trace (\"Test what onStatus messages exist in an average movie.\");" + "nc = new NetConnection ();" + "nc.connect (null);" + "ns = new NetStream (nc);" + "ns.onStatus = function (info) {" + " trace (\"NetStream onStatus called\");" + " trace (info.code);" + " trace (info.level);" + "};" + "video.attachVideo (ns);" + "ns.setBufferTime (5);" + "trace (\"Calling play\");" + "ns.play (\"video.flv\");" + "trace (\"done calling play\");" + ""); + SWFMovie_add (movie, (SWFBlock) action); + SWFMovie_save (movie, "netstream-onstatus.swf"); + return 0; +} diff --git a/test/trace/netstream-onstatus.swf b/test/trace/netstream-onstatus.swf new file mode 100644 index 0000000..dc9e39a Binary files /dev/null and b/test/trace/netstream-onstatus.swf differ diff --git a/test/trace/netstream-onstatus.swf.trace b/test/trace/netstream-onstatus.swf.trace new file mode 100644 index 0000000..c343359 --- /dev/null +++ b/test/trace/netstream-onstatus.swf.trace @@ -0,0 +1,12 @@ +Test what onStatus messages exist in an average movie. +Calling play +done calling play +NetStream onStatus called +NetStream.Play.Start +status +NetStream onStatus called +NetStream.Buffer.Flush +status +NetStream onStatus called +NetStream.Play.Stop +status diff --git a/test/trace/video.flv b/test/trace/video.flv new file mode 100644 index 0000000..7ce58aa Binary files /dev/null and b/test/trace/video.flv differ diff-tree 2f64500b40e8735c34ff65811ff8661f59621a22 (from ae8e75b794793b72bc11ab4da2212eed26473618) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 20:22:22 2007 +0100 implement NetStream.setBufferTime diff --git a/libswfdec/swfdec_js_net_stream.c b/libswfdec/swfdec_js_net_stream.c index f92634c..46cb1dc 100644 --- a/libswfdec/swfdec_js_net_stream.c +++ b/libswfdec/swfdec_js_net_stream.c @@ -43,8 +43,24 @@ swfdec_js_net_stream_play (JSContext *cx return JS_TRUE; } +static JSBool +swfdec_js_net_stream_set_buffer_time (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + SwfdecNetStream *stream; + double d; + + stream = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_NET_STREAM); + if (stream == NULL) + return JS_TRUE; + if (!JS_ValueToNumber (cx, argv[0], &d)) + return JS_FALSE; + swfdec_net_stream_set_buffer_time (stream, d); + return JS_TRUE; +} + static JSFunctionSpec net_stream_methods[] = { - { "play", swfdec_js_net_stream_play, 1, 0, 0 }, + { "play", swfdec_js_net_stream_play, 1, 0, 0 }, + { "setBufferTime", swfdec_js_net_stream_set_buffer_time, 1, 0, 0 }, {0,0,0,0,0} }; diff-tree ae8e75b794793b72bc11ab4da2212eed26473618 (from 06365380f68f96b17964c770cdca0600932b0805) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 20:21:27 2007 +0100 implement onStatus events includes quite a bit of refactoring in SwfdecNetStream and buffer time support diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c index da311d4..530915d 100644 --- a/libswfdec/swfdec_flv_decoder.c +++ b/libswfdec/swfdec_flv_decoder.c @@ -424,6 +424,29 @@ swfdec_flv_decoder_get_video (SwfdecFlvD return tag->buffer; } +gboolean +swfdec_flv_decoder_get_video_info (SwfdecFlvDecoder *flv, + guint *first_timestamp, guint *last_timestamp) +{ + g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), FALSE); + + if (flv->video == NULL) + return FALSE; + + if (flv->video->len == 0) { + if (first_timestamp) + *first_timestamp = 0; + if (last_timestamp) + *last_timestamp = 0; + return TRUE; + } + if (first_timestamp) + *first_timestamp = g_array_index (flv->video, SwfdecFlvVideoTag, 0).timestamp; + if (last_timestamp) + *last_timestamp = g_array_index (flv->video, SwfdecFlvVideoTag, flv->video->len - 1).timestamp; + return TRUE; +} + SwfdecBuffer * swfdec_flv_decoder_get_audio (SwfdecFlvDecoder *flv, guint timestamp, SwfdecAudioFormat *codec_format, gboolean *width, SwfdecAudioOut *format, @@ -489,6 +512,22 @@ notify_initialized (SwfdecPlayer *player swfdec_movie_invalidate (SWFDEC_MOVIE (movie)); } +gboolean +swfdec_flv_decoder_is_eof (SwfdecFlvDecoder *flv) +{ + g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), TRUE); + + 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; +} + SwfdecMovie * swfdec_flv_decoder_add_movie (SwfdecFlvDecoder *flv, SwfdecMovie *parent) { @@ -511,10 +550,8 @@ swfdec_flv_decoder_add_movie (SwfdecFlvD /* 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); + stream->flvdecoder = flv; swfdec_net_stream_set_loader (stream, SWFDEC_ROOT_MOVIE (parent)->loader); - 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); swfdec_net_stream_set_playing (stream, TRUE); g_object_unref (conn); diff --git a/libswfdec/swfdec_flv_decoder.h b/libswfdec/swfdec_flv_decoder.h index d3c5e0b..9163058 100644 --- a/libswfdec/swfdec_flv_decoder.h +++ b/libswfdec/swfdec_flv_decoder.h @@ -52,14 +52,18 @@ struct _SwfdecFlvDecoderClass { GType swfdec_flv_decoder_get_type (void); -SwfdecMovie * swfdec_flv_decoder_add_movie (SwfdecFlvDecoder * flv, - SwfdecMovie * parent); +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, gboolean keyframe, SwfdecVideoFormat * format, guint * real_timestamp, guint * next_timestamp); +gboolean swfdec_flv_decoder_get_video_info (SwfdecFlvDecoder * flv, + guint * first_timestamp, + guint * last_timestamp); SwfdecBuffer * swfdec_flv_decoder_get_audio (SwfdecFlvDecoder * flv, guint timestamp, SwfdecAudioFormat * codec_format, @@ -68,6 +72,8 @@ SwfdecBuffer * swfdec_flv_decoder_get_au guint * real_timestamp, guint * next_timestamp); +SwfdecMovie * swfdec_flv_decoder_add_movie (SwfdecFlvDecoder * flv, + SwfdecMovie * parent); G_END_DECLS #endif diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c index b524725..32651ad 100644 --- a/libswfdec/swfdec_net_stream.c +++ b/libswfdec/swfdec_net_stream.c @@ -26,8 +26,39 @@ #include "swfdec_debug.h" #include "swfdec_loader_internal.h" #include "swfdec_loadertarget.h" +#include "js/jsapi.h" static void +swfdec_net_stream_onstatus (SwfdecNetStream *stream, const char *code, const char *level) +{ + jsval val; + JSString *string; + JSObject *object; + JSContext *cx; + + cx = stream->player->jscx; + object = JS_NewObject (cx, NULL, NULL, NULL); + if (!object) + return; + string = JS_NewStringCopyZ (cx, code); + if (!string) + return; + val = STRING_TO_JSVAL (string); + if (!JS_SetProperty (cx, object, "code", &val)) + return; + string = JS_NewStringCopyZ (cx, level); + if (!string) + return; + val = STRING_TO_JSVAL (string); + if (!JS_SetProperty (cx, object, "level", &val)) + return; + + val = OBJECT_TO_JSVAL (object); + swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (stream), "onStatus", 1, &val); +} + +static void swfdec_net_stream_update_playing (SwfdecNetStream *stream); +static void swfdec_net_stream_video_goto (SwfdecNetStream *stream, guint timestamp) { SwfdecBuffer *buffer; @@ -76,6 +107,15 @@ swfdec_net_stream_video_goto (SwfdecNetS } } } + if (stream->next_time <= stream->current_time) { + if (swfdec_flv_decoder_is_eof (stream->flvdecoder)) { + swfdec_net_stream_onstatus (stream, "NetStream.Play.Stop", "status"); + } else { + stream->buffering = TRUE; + swfdec_net_stream_onstatus (stream, "NetStream.Buffer.Empty", "status"); + } + swfdec_net_stream_update_playing (stream); + } } static void @@ -84,13 +124,13 @@ swfdec_net_stream_timeout (SwfdecTimeout SwfdecNetStream *stream = SWFDEC_NET_STREAM ((guchar *) timeout - G_STRUCT_OFFSET (SwfdecNetStream, timeout)); SWFDEC_LOG ("timeout fired"); + stream->timeout.callback = NULL; swfdec_net_stream_video_goto (stream, stream->next_time); if (stream->next_time > stream->current_time) { SWFDEC_LOG ("readding timeout"); stream->timeout.timestamp += SWFDEC_MSECS_TO_TICKS (stream->next_time - stream->current_time); + stream->timeout.callback = swfdec_net_stream_timeout; swfdec_player_add_timeout (stream->player, &stream->timeout); - } else { - stream->timeout.callback = NULL; } } @@ -100,8 +140,9 @@ swfdec_net_stream_update_playing (Swfdec gboolean should_play; should_play = stream->playing; + should_play &= !stream->buffering; should_play &= stream->flvdecoder != NULL; - should_play &= stream->next_time > stream->current_time; + //should_play &= stream->next_time > stream->current_time; if (should_play && stream->timeout.callback == NULL) { SWFDEC_DEBUG ("starting playback"); stream->timeout.callback = swfdec_net_stream_timeout; @@ -135,58 +176,89 @@ swfdec_net_stream_loader_target_get_play return SWFDEC_NET_STREAM (target)->player; } -static SwfdecDecoder * -swfdec_net_stream_loader_target_get_decoder (SwfdecLoaderTarget *target) -{ - return SWFDEC_DECODER (SWFDEC_NET_STREAM (target)->flvdecoder); -} - -static gboolean -swfdec_net_stream_loader_target_set_decoder (SwfdecLoaderTarget *target, - SwfdecDecoder *decoder) +static void +swfdec_net_stream_loader_target_parse (SwfdecLoaderTarget *target, + SwfdecLoader *loader) { SwfdecNetStream *stream = SWFDEC_NET_STREAM (target); + SwfdecDecoderClass *klass; + gboolean recheck = FALSE; + + if (loader->error) { + if (stream->flvdecoder == NULL) + swfdec_net_stream_onstatus (stream, "NetStream.Play.StreamNotFound", "error"); + return; + } + if (!loader->eof && swfdec_buffer_queue_get_depth (loader->queue) == 0) { + SWFDEC_WARNING ("nothing to parse?!"); + return; + } + if (stream->flvdecoder == NULL) { + /* FIXME: add mp3 support */ + stream->flvdecoder = g_object_new (SWFDEC_TYPE_FLV_DECODER, NULL); + SWFDEC_DECODER (stream->flvdecoder)->player = stream->player; + SWFDEC_DECODER (stream->flvdecoder)->queue = loader->queue; + swfdec_net_stream_onstatus (stream, "NetStream.Play.Start", "status"); + } + klass = SWFDEC_DECODER_GET_CLASS (stream->flvdecoder); + g_return_if_fail (klass->parse); - if (!SWFDEC_IS_FLV_DECODER (decoder)) { - g_object_unref (decoder); - return FALSE; + while (TRUE) { + SwfdecStatus status = klass->parse (SWFDEC_DECODER (stream->flvdecoder)); + switch (status) { + case SWFDEC_STATUS_OK: + break; + case SWFDEC_STATUS_INIT: + /* HACK for native flv playback */ + swfdec_player_initialize (stream->player, + SWFDEC_DECODER (stream->flvdecoder)->rate, + SWFDEC_DECODER (stream->flvdecoder)->width, + SWFDEC_DECODER (stream->flvdecoder)->height); + case SWFDEC_STATUS_IMAGE: + recheck = TRUE; + break; + case SWFDEC_STATUS_ERROR: + case SWFDEC_STATUS_NEEDBITS: + goto out; + case SWFDEC_STATUS_EOF: + /* the flv decoder never emits this */ + default: + g_assert_not_reached (); + return; + } + } +out: + if (loader->eof) { + swfdec_flv_decoder_eof (stream->flvdecoder); + recheck = TRUE; + swfdec_net_stream_onstatus (stream, "NetStream.Buffer.Flush", "status"); + swfdec_net_stream_video_goto (stream, stream->current_time); + stream->buffering = FALSE; + } + if (recheck) { + if (stream->buffering) { + guint first, last; + if (swfdec_flv_decoder_get_video_info (stream->flvdecoder, &first, &last)) { + guint current = MAX (first, stream->current_time); + if (current + stream->buffer_time <= last) { + swfdec_net_stream_video_goto (stream, current); + stream->buffering = FALSE; + swfdec_net_stream_onstatus (stream, "NetStream.Buffer.Full", "status"); + } + } else { + SWFDEC_ERROR ("no video stream, how do we update buffering?"); + } + } + swfdec_net_stream_update_playing (stream); } - stream->flvdecoder = SWFDEC_FLV_DECODER (decoder); - swfdec_net_stream_update_playing (stream); - return TRUE; } -static gboolean -swfdec_net_stream_loader_target_image (SwfdecLoaderTarget *target) -{ - SwfdecNetStream *stream = SWFDEC_NET_STREAM (target); - guint current, next; - SwfdecBuffer *buffer; - SwfdecVideoFormat format; - - if (!stream->playing) - return TRUE; - - buffer = swfdec_flv_decoder_get_video (stream->flvdecoder, - stream->current_time, FALSE, &format, ¤t, &next); - if (format != stream->format || - stream->current_time != current || - stream->next_time != next) - swfdec_net_stream_video_goto (stream, current); - swfdec_net_stream_update_playing (stream); - - return TRUE; -} static void swfdec_net_stream_loader_target_init (SwfdecLoaderTargetInterface *iface) { iface->get_player = swfdec_net_stream_loader_target_get_player; - iface->get_decoder = swfdec_net_stream_loader_target_get_decoder; - iface->set_decoder = swfdec_net_stream_loader_target_set_decoder; - - iface->init = swfdec_net_stream_loader_target_image; - iface->image = swfdec_net_stream_loader_target_image; + iface->parse = swfdec_net_stream_loader_target_parse; } /*** SWFDEC VIDEO MOVIE INPUT ***/ @@ -251,6 +323,8 @@ swfdec_net_stream_init (SwfdecNetStream { stream->input.connect = swfdec_net_stream_input_connect; stream->input.disconnect = swfdec_net_stream_input_disconnect; + + stream->buffer_time = 100; /* msecs */ } SwfdecNetStream * @@ -264,6 +338,7 @@ swfdec_net_stream_new (SwfdecPlayer *pla stream = g_object_new (SWFDEC_TYPE_NET_STREAM, NULL); stream->player = player; stream->conn = conn; + SWFDEC_SCRIPTABLE (stream)->jscx = player->jscx; g_object_ref (conn); return stream; @@ -295,6 +370,7 @@ swfdec_net_stream_set_loader (SwfdecNetS stream->flvdecoder = NULL; } stream->loader = loader; + stream->buffering = TRUE; if (loader) { g_object_ref (loader); swfdec_loader_set_target (loader, SWFDEC_LOADER_TARGET (stream)); @@ -321,3 +397,23 @@ swfdec_net_stream_get_playing (SwfdecNet return stream->playing; } +void +swfdec_net_stream_set_buffer_time (SwfdecNetStream *stream, double secs) +{ + g_return_if_fail (SWFDEC_IS_NET_STREAM (stream)); + + /* FIXME: is this correct? */ + if (secs <= 0) + return; + + stream->buffer_time = secs * 1000; +} + +double +swfdec_net_stream_get_buffer_time (SwfdecNetStream *stream) +{ + g_return_val_if_fail (SWFDEC_IS_NET_STREAM (stream), 0.1); + + return (double) stream->buffer_time / 1000.0; +} + diff --git a/libswfdec/swfdec_net_stream.h b/libswfdec/swfdec_net_stream.h index ce22330..c36c45a 100644 --- a/libswfdec/swfdec_net_stream.h +++ b/libswfdec/swfdec_net_stream.h @@ -48,8 +48,12 @@ struct _SwfdecNetStream SwfdecLoader * loader; /* input stream */ SwfdecFlvDecoder * flvdecoder; /* flv decoder */ gboolean playing; /* TRUE if this stream is playing */ + gboolean buffering; /* TRUE if we're waiting for more input data */ gboolean error; /* in error */ + /* properties */ + guint buffer_time; /* buffering time in msecs */ + /* video decoding */ guint current_time; /* current playback timestamp */ guint next_time; /* next video image at this timestamp */ @@ -82,6 +86,9 @@ void swfdec_net_stream_set_loader (Swf void swfdec_net_stream_set_playing (SwfdecNetStream * stream, gboolean playing); gboolean swfdec_net_stream_get_playing (SwfdecNetStream * stream); +void swfdec_net_stream_set_buffer_time (SwfdecNetStream * stream, + double secs); +double swfdec_net_stream_get_buffer_time (SwfdecNetStream * stream); G_END_DECLS diff-tree 06365380f68f96b17964c770cdca0600932b0805 (from db754a85ebcee98643d8d4d40998d759bdb7b01a) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 19:42:27 2007 +0100 Fix crash when setInterval is used with arguments diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c index bab231a..02e9a55 100644 --- a/libswfdec/swfdec_js_global.c +++ b/libswfdec/swfdec_js_global.c @@ -139,7 +139,7 @@ swfdec_js_global_setInterval (JSContext interval->msecs = msecs; interval->vals[0] = fun; interval->vals[1] = OBJECT_TO_JSVAL (object); - memcpy (&interval->vals[2], &argv[first_arg], n_args); + memcpy (&interval->vals[2], &argv[first_arg], n_args * sizeof (jsval)); for (i = 0; i < n_args + 2; i++) { if (!JS_AddRoot (cx, &interval->vals[i])) { /* FIXME: is it save roots that weren't added before? */ diff-tree db754a85ebcee98643d8d4d40998d759bdb7b01a (from be5455d2287e0d4c7b6ee2770ce72b3022a840c6) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 19:40:19 2007 +0100 add currently crashing test diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am index ed2582f..3b50bae 100644 --- a/test/trace/Makefile.am +++ b/test/trace/Makefile.am @@ -141,6 +141,9 @@ EXTRA_DIST = \ setinterval.swf.trace setinterval2.swf \ setinterval2.swf.trace \ + setinterval-arguments.as \ + setinterval-arguments.swf \ + setinterval-arguments.swf.trace \ setinterval-clear.swf \ setinterval-clear.swf.trace \ setvariable.swf \ diff --git a/test/trace/setinterval-arguments.as b/test/trace/setinterval-arguments.as new file mode 100644 index 0000000..7d88ef1 --- /dev/null +++ b/test/trace/setinterval-arguments.as @@ -0,0 +1,4 @@ +// makeswf -v 7 -s 200x150 -r 1 -o setinterval-arguments.swf setinterval-arguments.as + +trace ("Check arguments to setInterval work"); +setInterval (function (a, b, c) { trace (a); trace (b); trace (c); }, 7000, 1, 42, "hi"); diff --git a/test/trace/setinterval-arguments.swf b/test/trace/setinterval-arguments.swf new file mode 100644 index 0000000..2ba1086 Binary files /dev/null and b/test/trace/setinterval-arguments.swf differ diff --git a/test/trace/setinterval-arguments.swf.trace b/test/trace/setinterval-arguments.swf.trace new file mode 100644 index 0000000..827154e --- /dev/null +++ b/test/trace/setinterval-arguments.swf.trace @@ -0,0 +1,4 @@ +Check arguments to setInterval work +1 +42 +hi diff-tree be5455d2287e0d4c7b6ee2770ce72b3022a840c6 (from 97490d426827b5adbb2205f904c83f51ab836223) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 17:14:54 2007 +0100 use the movie's JSClass this makes Video::attachVideo work again diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c index e0f3f54..1504e3d 100644 --- a/libswfdec/swfdec_js_movie.c +++ b/libswfdec/swfdec_js_movie.c @@ -1248,7 +1248,8 @@ swfdec_js_movie_create_jsobject (SwfdecM (fun = swfdec_js_movie_lookup_class (SWFDEC_SPRITE_MOVIE (movie))) != JSVAL_NULL) { swfdec_js_construct_object (script->jscx, &movieclip_class, fun, &script->jsobj); } else { - script->jsobj = JS_NewObject (script->jscx, &movieclip_class, + SwfdecScriptableClass *klass = SWFDEC_SCRIPTABLE_GET_CLASS (movie); + script->jsobj = JS_NewObject (script->jscx, klass->jsclass, NULL, NULL); } if (!script->jsobj || diff-tree 97490d426827b5adbb2205f904c83f51ab836223 (from 318f367d0a5fe8efaff7861b06baaaebbc9dd7db) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 15:46:20 2007 +0100 change sematics of trace test slightly Instead of advancing 10 times, the movie advances until 10 / rate seconds have passed. No test needs to be changed for this. diff --git a/test/trace/README b/test/trace/README index 1593365..f6ae935 100644 --- a/test/trace/README +++ b/test/trace/README @@ -5,13 +5,13 @@ How does it work? ./trace [FILE1 [FILE2 [...]]] The program trace in this directory takes all files on the command line or all files in the current directory and runs them. Running consists of instancing a -SwfdecPlayer and iterating $FILE 10 times. Everytime the trace function is -invoked by that player, its output is appended to a buffer. After this the -captured output is compared to the file $FILE.trace. If the output matches, the -test succeeded for the given file, otherwise it failed. In this case a diff is -produced and dumped to stdout. The captured trace output is written to a file -named "tmp". The return value is 0 if all tests passed, or failure if at least -one test failed. +SwfdecPlayer and iterating $FILE until 10 frames have passed. Everytime the +trace function is invoked by that player, its output is appended to a buffer. +Finally the captured output is compared to the file $FILE.trace. If the output +matches, the test succeeded for the given file, otherwise it failed. In this +case a diff is produced and dumped to stdout. The captured trace output is +written to a file named "tmp". The return value is 0 if all tests passed, or +failure if at least one test failed. How do I run my new test? diff --git a/test/trace/trace.c b/test/trace/trace.c index d2fee65..9a5a841 100644 --- a/test/trace/trace.c +++ b/test/trace/trace.c @@ -1,6 +1,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include <math.h> #include <string.h> #include <libswfdec/swfdec.h> @@ -16,7 +17,7 @@ run_test (const char *filename) SwfdecLoader *loader; SwfdecPlayer *player; SwfdecBuffer *buffer; - guint i; + guint time_left; GError *error = NULL; char *str; GString *string; @@ -31,12 +32,22 @@ run_test (const char *filename) player = swfdec_player_new (); g_signal_connect (player, "trace", G_CALLBACK (trace_cb), string); swfdec_player_set_loader (player, loader); + if (!swfdec_player_is_initialized (player)) { + g_print (" ERROR: player is not initialized\n"); + g_object_unref (player); + return FALSE; + } + time_left = ceil (10000 / swfdec_player_get_rate (player)); /* FIXME: Make the number of iterations configurable? */ - for (i = 0; i < 10; i++) { + while (TRUE) { /* FIXME: will not do 10 iterations if there's other stuff loaded */ guint advance = swfdec_player_get_next_event (player); + + if (advance > time_left) + break; swfdec_player_advance (player, advance); + time_left -= advance; } g_signal_handlers_disconnect_by_func (player, trace_cb, string); g_object_unref (player); diff-tree 318f367d0a5fe8efaff7861b06baaaebbc9dd7db (from cfd5a7fd62cf9b2ccb30338e1ce22da5e6a04840) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 14:48:30 2007 +0100 Don't return immediately in swfdec_loader_target_parse if the loader is in error Also update the hack for native FLV loading to call swfdec_loader_target_parse when the loader changed instead of just cninuing. This allows different parse functions in different targets. diff --git a/libswfdec/swfdec_loadertarget.c b/libswfdec/swfdec_loadertarget.c index 3212fc8..40ad26f 100644 --- a/libswfdec/swfdec_loadertarget.c +++ b/libswfdec/swfdec_loadertarget.c @@ -97,7 +97,11 @@ swfdec_loader_target_parse_default (Swfd swfdec_loader_error_locked (loader, "Internal error"); return; } - target = loader->target; + /* HACK for flv playback */ + if (target != loader->target) { + swfdec_loader_target_parse (loader->target, loader); + return; + } } klass = SWFDEC_DECODER_GET_CLASS (dec); g_return_if_fail (klass->parse); @@ -150,8 +154,6 @@ swfdec_loader_target_parse (SwfdecLoader SWFDEC_LOG ("parsing %p%s%s", loader, loader->error ? " ERROR" : "", loader->eof ? " EOF" : ""); - if (loader->error) - return; iface = SWFDEC_LOADER_TARGET_GET_INTERFACE (target); if (iface->parse == NULL) { diff-tree cfd5a7fd62cf9b2ccb30338e1ce22da5e6a04840 (from 467707141d1d5daa08fe9ebff8bcdfb7ed0abac1) Author: Benjamin Otte <otte@gnome.org> Date: Wed Mar 14 14:47:00 2007 +0100 change the way swfdec_loader_load works. swfdec_loader_load now always returns a loader. If there was an error creating the loader, the loader will have been put in the error state on creation. diff --git a/libswfdec/swfdec_loader.c b/libswfdec/swfdec_loader.c index 22f418b..4334562 100644 --- a/libswfdec/swfdec_loader.c +++ b/libswfdec/swfdec_loader.c @@ -191,17 +191,16 @@ swfdec_file_loader_load (SwfdecLoader *l /* FIXME: need to rework seperators on windows? */ real_path = g_build_filename (SWFDEC_FILE_LOADER (loader)->dir, url, NULL); buffer = swfdec_buffer_new_from_file (real_path, &error); - if (buffer == NULL) { - SWFDEC_ERROR ("Couldn't load \"%s\": %s", real_path, error->message); - g_free (real_path); - g_error_free (error); - return NULL; - } ret = g_object_new (SWFDEC_TYPE_FILE_LOADER, NULL); ret->url = real_path; SWFDEC_FILE_LOADER (ret)->dir = g_strdup (SWFDEC_FILE_LOADER (loader)->dir); - swfdec_loader_push (ret, buffer); - swfdec_loader_eof (ret); + if (buffer == NULL) { + swfdec_loader_error (ret, error->message); + g_error_free (error); + } else { + swfdec_loader_push (ret, buffer); + swfdec_loader_eof (ret); + } return ret; } @@ -227,6 +226,7 @@ swfdec_file_loader_init (SwfdecFileLoade SwfdecLoader * swfdec_loader_load (SwfdecLoader *loader, const char *url) { + SwfdecLoader *ret; SwfdecLoaderClass *klass; g_return_val_if_fail (SWFDEC_IS_LOADER (loader), NULL); @@ -234,7 +234,9 @@ swfdec_loader_load (SwfdecLoader *loader klass = SWFDEC_LOADER_GET_CLASS (loader); g_return_val_if_fail (klass->load != NULL, NULL); - return klass->load (loader, url); + ret = klass->load (loader, url); + g_assert (ret != NULL); + return ret; } void @@ -321,15 +323,20 @@ swfdec_loader_error (SwfdecLoader *loade g_return_if_fail (SWFDEC_IS_LOADER (loader)); g_return_if_fail (error != NULL); - SWFDEC_ERROR ("error in loader %p: %s", loader, error); - if (loader->error) + if (loader->error) { + SWFDEC_ERROR ("another error in loader %p: %s", loader, error); return; + } - player = swfdec_loader_target_get_player (loader->target); - swfdec_player_lock (player); - swfdec_loader_error_locked (loader, error); - swfdec_player_perform_actions (player); - swfdec_player_unlock (player); + if (loader->target) { + player = swfdec_loader_target_get_player (loader->target); + swfdec_player_lock (player); + swfdec_loader_error_locked (loader, error); + swfdec_player_perform_actions (player); + swfdec_player_unlock (player); + } else { + swfdec_loader_error_locked (loader, error); + } } void @@ -338,10 +345,11 @@ swfdec_loader_error_locked (SwfdecLoader if (loader->error) return; - SWFDEC_ERROR ("error in loader %p: %s", loader, error); + SWFDEC_WARNING ("error in %s %p: %s", G_OBJECT_TYPE_NAME (loader), loader, error); loader->error = g_strdup (error); g_object_notify (G_OBJECT (loader), "error"); - swfdec_loader_target_parse (loader->target, loader); + if (loader->target) + swfdec_loader_target_parse (loader->target, loader); } void diff --git a/libswfdec/swfdec_loader.h b/libswfdec/swfdec_loader.h index 87153b4..c6bc678 100644 --- a/libswfdec/swfdec_loader.h +++ b/libswfdec/swfdec_loader.h @@ -52,7 +52,7 @@ struct _SwfdecLoaderClass { GObjectClass object_class; - /* FIXME: better error reporting? */ + /* loads the given URL. Must return a loader, the loader can be in the error state */ SwfdecLoader * (* load) (SwfdecLoader * loader, const char * url); };
Seemingly Similar Threads
- 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
- 11 commits - libswfdec/swfdec_color.c libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_js_net_stream.c libswfdec/swfdec_movie.c libswfdec/swfdec_net_stream.c libswfdec/swfdec_net_stream.h libswfdec/swfdec_pattern.c libswfdec/swfdec_script.c NEWS test/trace
- 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
- Branch 'as' - 5 commits - libswfdec/Makefile.am libswfdec/swfdec_as_strings.c libswfdec/swfdec_js_net_stream.c libswfdec/swfdec_movie.c libswfdec/swfdec_net_connection.c libswfdec/swfdec_net_stream_as.c libswfdec/swfdec_net_stream.c
- 11 commits - libswfdec/Makefile.am libswfdec/swfdec_connection.c libswfdec/swfdec_connection.h libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_js.c libswfdec/swfdec_js_connection.c libswfdec/swfdec_js.h libswfdec/swfdec_js_net_stream.c