Benjamin Otte
2007-Mar-20 05:59 UTC
[Swfdec] 3 commits - libswfdec/Makefile.am libswfdec/swfdec_amf.c libswfdec/swfdec_amf.h libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_net_stream.c
libswfdec/Makefile.am | 2 libswfdec/swfdec_amf.c | 230 ++++++++++++++++++++++++++++++++++++++++++ libswfdec/swfdec_amf.h | 59 ++++++++++ libswfdec/swfdec_bits.c | 22 ++++ libswfdec/swfdec_bits.h | 1 libswfdec/swfdec_net_stream.c | 24 ++++ 6 files changed, 338 insertions(+) New commits: diff-tree 82bed9c9883df0ea0d012b8c59a8d4986175c671 (from 6e035c9fca2f71563f5fc1a4561fedaa04600f3f) Author: Benjamin Otte <otte@gnome.org> Date: Tue Mar 20 13:58:19 2007 +0100 handle data tags by calling a function on the NEtStream object using the AMF-decoded data. diff --git a/libswfdec/swfdec_net_stream.c b/libswfdec/swfdec_net_stream.c index b722095..e9b251a 100644 --- a/libswfdec/swfdec_net_stream.c +++ b/libswfdec/swfdec_net_stream.c @@ -22,6 +22,7 @@ #endif #include "swfdec_net_stream.h" +#include "swfdec_amf.h" #include "swfdec_audio_flv.h" #include "swfdec_debug.h" #include "swfdec_loader_internal.h" @@ -65,8 +66,12 @@ swfdec_net_stream_video_goto (SwfdecNetS SwfdecBuffer *buffer; SwfdecVideoFormat format; cairo_surface_t *old; + gboolean process_events; + guint process_events_from; SWFDEC_LOG ("goto %ums", timestamp); + process_events = timestamp == stream->next_time; + process_events_from = MIN (stream->next_time, stream->current_time + 1); buffer = swfdec_flv_decoder_get_video (stream->flvdecoder, timestamp, FALSE, &format, &stream->current_time, &stream->next_time); old = stream->surface; @@ -117,6 +122,25 @@ swfdec_net_stream_video_goto (SwfdecNetS } swfdec_net_stream_update_playing (stream); } + if (process_events) { + while (process_events_from <= stream->current_time) { + jsval name, value; + SwfdecBits bits; + SwfdecBuffer *event = swfdec_flv_decoder_get_data (stream->flvdecoder, process_events_from, &process_events_from); + if (!event) + break; + SWFDEC_LOG ("processing event from timestamp %u", process_events_from); + process_events_from++; /* increase so we get the next event next time */ + swfdec_bits_init (&bits, event); + if (swfdec_amf_parse (SWFDEC_SCRIPTABLE (stream)->jscx, &bits, 2, + SWFDEC_AMF_STRING, &name, SWFDEC_AMF_MIXED_ARRAY, &value) != 2) { + SWFDEC_ERROR ("could not parse data tag"); + } else { + swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (stream), + JS_GetStringBytes (JSVAL_TO_STRING (name)), 1, &value); + } + } + } } static void diff-tree 6e035c9fca2f71563f5fc1a4561fedaa04600f3f (from e4e0c60341b918ffb5637502afd157cd2bfbd366) Author: Benjamin Otte <otte@gnome.org> Date: Tue Mar 20 13:57:42 2007 +0100 add initial support for handling AMF encoded data diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am index ecd16aa..1270262 100644 --- a/libswfdec/Makefile.am +++ b/libswfdec/Makefile.am @@ -16,6 +16,7 @@ lib_LTLIBRARIES = libswfdec-@SWFDEC_MAJO js_cflags = -I$(srcdir)/js/ -I./js -DXP_UNIX -DDEBUG libswfdec_@SWFDEC_MAJORMINOR@_la_SOURCES = \ + swfdec_amf.c \ swfdec_audio.c \ swfdec_audio_event.c \ swfdec_audio_flv.c \ @@ -105,6 +106,7 @@ libswfdec_@SWFDEC_MAJORMINOR@includedir libswfdec_@SWFDEC_MAJORMINOR@include_HEADERS = $(public_headers) swfdec_enums.h noinst_HEADERS = \ + swfdec_amf.h \ swfdec_audio_internal.h \ swfdec_audio_event.h \ swfdec_audio_flv.h \ diff --git a/libswfdec/swfdec_amf.c b/libswfdec/swfdec_amf.c new file mode 100644 index 0000000..e1ac8ba --- /dev/null +++ b/libswfdec/swfdec_amf.c @@ -0,0 +1,230 @@ +/* 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 + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "swfdec_amf.h" +#include "swfdec_bits.h" +#include "swfdec_debug.h" +#include "js/jsapi.h" + +typedef gboolean (* SwfdecAmfParseFunc) (JSContext *cx, SwfdecBits *bits, jsval *val); +extern const SwfdecAmfParseFunc parse_funcs[SWFDEC_AMF_N_TYPES]; + +static gboolean +swfdec_amf_parse_boolean (JSContext *cx, SwfdecBits *bits, jsval *val) +{ + *val = swfdec_bits_get_u8 (bits) ? JSVAL_TRUE : JSVAL_FALSE; + return TRUE; +} + +static gboolean +swfdec_amf_parse_number (JSContext *cx, SwfdecBits *bits, jsval *val) +{ + double d = swfdec_bits_get_bdouble (bits); + + if (!JS_NewNumberValue (cx, d, val)) + return FALSE; + return TRUE; +} + +static gboolean +swfdec_amf_parse_string (JSContext *cx, SwfdecBits *bits, jsval *val) +{ + guint len = swfdec_bits_get_bu16 (bits); + char *s; + JSString *string; + + s = swfdec_bits_get_string_length (bits, len); + if (s == NULL) + return FALSE; + + string = JS_NewStringCopyZ (cx, s); + g_free (s); + if (!string) + return FALSE; + *val = STRING_TO_JSVAL (string); + return TRUE; +} +static gboolean +swfdec_amf_parse_properties (JSContext *cx, SwfdecBits *bits, jsval *val) +{ + guint type; + SwfdecAmfParseFunc func; + JSObject *object; + + g_assert (JSVAL_IS_OBJECT (*val)); + object = JSVAL_TO_OBJECT (*val); + + while (swfdec_bits_left (bits)) { + jsval id, val; + if (!swfdec_amf_parse_string (cx, bits, &id)) + return FALSE; + type = swfdec_bits_get_u8 (bits); + if (type == SWFDEC_AMF_END_OBJECT) + return TRUE; + if (type >= SWFDEC_AMF_N_TYPES || + (func = parse_funcs[type]) == NULL) { + SWFDEC_ERROR ("no parse func for AMF type %u", type); + return FALSE; + } + if (!func (cx, bits, &val)) + return FALSE; + if (!JS_SetProperty (cx, object, JS_GetStringBytes (JSVAL_TO_STRING (id)), &val)) + return FALSE; + } + /* no more bytes seems to end automatically */ + return TRUE; +} + +static gboolean +swfdec_amf_parse_object (JSContext *cx, SwfdecBits *bits, jsval *val) +{ + JSObject *object; + + object = JS_NewObject (cx, NULL, NULL, NULL); + if (object == NULL) + return FALSE; + + *val = OBJECT_TO_JSVAL (object); + return swfdec_amf_parse_properties (cx, bits, val); +} + +static gboolean +swfdec_amf_parse_mixed_array (JSContext *cx, SwfdecBits *bits, jsval *val) +{ + guint len; + JSObject *object; + + len = swfdec_bits_get_bu32 (bits); + object = JS_NewArrayObject (cx, len, NULL); + if (object == NULL) + return FALSE; + + *val = OBJECT_TO_JSVAL (object); + return swfdec_amf_parse_properties (cx, bits, val); +} + +static gboolean +swfdec_amf_parse_array (JSContext *cx, SwfdecBits *bits, jsval *val) +{ + guint i, len; + JSObject *object; + jsval *vector; + guint type; + SwfdecAmfParseFunc func; + + len = swfdec_bits_get_bu32 (bits); + vector = g_try_new (jsval, len); + if (vector == NULL) + return FALSE; + for (i = 0; i < len; i++) { + type = swfdec_bits_get_u8 (bits); + if (type >= SWFDEC_AMF_N_TYPES || + (func = parse_funcs[type]) == NULL) { + SWFDEC_ERROR ("no parse func for AMF type %u", type); + goto fail; + } + if (!func (cx, bits, &vector[i])) + goto fail; + } + object = JS_NewArrayObject (cx, len, vector); + if (object == NULL) + goto fail; + + *val = OBJECT_TO_JSVAL (object); + g_free (vector); + return TRUE; + +fail: + g_free (vector); + return FALSE; +} + +const SwfdecAmfParseFunc parse_funcs[SWFDEC_AMF_N_TYPES] = { + [SWFDEC_AMF_NUMBER] = swfdec_amf_parse_number, + [SWFDEC_AMF_BOOLEAN] = swfdec_amf_parse_boolean, + [SWFDEC_AMF_STRING] = swfdec_amf_parse_string, + [SWFDEC_AMF_OBJECT] = swfdec_amf_parse_object, + [SWFDEC_AMF_MIXED_ARRAY] = swfdec_amf_parse_mixed_array, + [SWFDEC_AMF_ARRAY] = swfdec_amf_parse_array, +#if 0 + SWFDEC_AMF_MOVIECLIP = 4, + SWFDEC_AMF_NULL = 5, + SWFDEC_AMF_UNDEFINED = 6, + SWFDEC_AMF_REFERENCE = 7, + SWFDEC_AMF_END_OBJECT = 9, + SWFDEC_AMF_ARRAY = 10, + SWFDEC_AMF_DATE = 11, + SWFDEC_AMF_BIG_STRING = 12, + SWFDEC_AMF_RECORDSET = 14, + SWFDEC_AMF_XML = 15, + SWFDEC_AMF_CLASS = 16, + SWFDEC_AMF_FLASH9 = 17, +#endif +}; + +gboolean +swfdec_amf_parse_one (JSContext *cx, SwfdecBits *bits, SwfdecAmfType expected_type, + jsval *rval) +{ + SwfdecAmfParseFunc func; + guint type; + + g_return_val_if_fail (cx != NULL, FALSE); + g_return_val_if_fail (bits != NULL, FALSE); + g_return_val_if_fail (rval != NULL, FALSE); + g_return_val_if_fail (expected_type < SWFDEC_AMF_N_TYPES, FALSE); + + type = swfdec_bits_get_u8 (bits); + if (type != expected_type) { + SWFDEC_ERROR ("parse object should be type %u, but is %u", + expected_type, type); + return FALSE; + } + if (type >= SWFDEC_AMF_N_TYPES || + (func = parse_funcs[type]) == NULL) { + SWFDEC_ERROR ("no parse func for AMF type %u", type); + return FALSE; + } + return func (cx, bits, rval); +} + +guint +swfdec_amf_parse (JSContext *cx, SwfdecBits *bits, guint n_items, ...) +{ + va_list args; + guint i; + + g_return_val_if_fail (cx != NULL, 0); + g_return_val_if_fail (bits != NULL, 0); + + va_start (args, n_items); + for (i = 0; i < n_items; i++) { + SwfdecAmfType type = va_arg (args, SwfdecAmfType); + jsval *val = va_arg (args, jsval *); + if (!swfdec_amf_parse_one (cx, bits, type, val)) + break; + } + va_end (args); + return i; +} + diff --git a/libswfdec/swfdec_amf.h b/libswfdec/swfdec_amf.h new file mode 100644 index 0000000..564fbb5 --- /dev/null +++ b/libswfdec/swfdec_amf.h @@ -0,0 +1,59 @@ +/* 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 + */ + +#ifndef __SWFDEC_AMF_H__ +#define __SWFDEC_AMF_H__ + +#include <libswfdec/js/jspubtd.h> +#include <libswfdec/swfdec_bits.h> + +typedef enum { + SWFDEC_AMF_NUMBER = 0, + SWFDEC_AMF_BOOLEAN = 1, + SWFDEC_AMF_STRING = 2, + SWFDEC_AMF_OBJECT = 3, + SWFDEC_AMF_MOVIECLIP = 4, + SWFDEC_AMF_NULL = 5, + SWFDEC_AMF_UNDEFINED = 6, + SWFDEC_AMF_REFERENCE = 7, + SWFDEC_AMF_MIXED_ARRAY = 8, + SWFDEC_AMF_END_OBJECT = 9, + SWFDEC_AMF_ARRAY = 10, + SWFDEC_AMF_DATE = 11, + SWFDEC_AMF_BIG_STRING = 12, + /* what is 13? */ + SWFDEC_AMF_RECORDSET = 14, + SWFDEC_AMF_XML = 15, + SWFDEC_AMF_CLASS = 16, + SWFDEC_AMF_FLASH9 = 17, + /* add more items here */ + SWFDEC_AMF_N_TYPES +} SwfdecAmfType; + +gboolean swfdec_amf_parse_one (JSContext * cx, + SwfdecBits * bits, + SwfdecAmfType expected_type, + jsval * rval); +guint swfdec_amf_parse (JSContext * cx, + SwfdecBits * bits, + guint n_items, + ...); + + +#endif diff-tree e4e0c60341b918ffb5637502afd157cd2bfbd366 (from 9395d4ef15746d3e1d7070a13f6da03a91c67b54) Author: Benjamin Otte <otte@gnome.org> Date: Tue Mar 20 13:56:52 2007 +0100 add swfdec_bits_get_bdouble for querying big endian doubles diff --git a/libswfdec/swfdec_bits.c b/libswfdec/swfdec_bits.c index 860d2c4..19b1dcd 100644 --- a/libswfdec/swfdec_bits.c +++ b/libswfdec/swfdec_bits.c @@ -322,6 +322,28 @@ swfdec_bits_get_double (SwfdecBits * b) return d; } +double +swfdec_bits_get_bdouble (SwfdecBits * b) +{ + double d; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + guint64 tmp; +#endif + + SWFDEC_BYTES_CHECK (b, 8); + +#if G_BYTE_ORDER == G_BIG_ENDIAN + d = *((double *) b->ptr); +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN + tmp = *((guint64 *) b->ptr); + tmp = GUINT64_FROM_BE (tmp); + d = *((double *) &tmp); +#endif + b->ptr += 8; + + return d; +} + void swfdec_bits_syncbits (SwfdecBits * b) { diff --git a/libswfdec/swfdec_bits.h b/libswfdec/swfdec_bits.h index d568dd8..ac07746 100644 --- a/libswfdec/swfdec_bits.h +++ b/libswfdec/swfdec_bits.h @@ -53,6 +53,7 @@ unsigned int swfdec_bits_get_bu24 (Swfde unsigned int swfdec_bits_get_bu32 (SwfdecBits *b); float swfdec_bits_get_float (SwfdecBits * b); double swfdec_bits_get_double (SwfdecBits * b); +double swfdec_bits_get_bdouble (SwfdecBits * b); void swfdec_bits_syncbits (SwfdecBits * b); void swfdec_bits_get_color_transform (SwfdecBits * bits,