void start_sound_loader(stream* in, int tag_type, movie_definition_sub* m) // Load a StartSound tag. { assert(tag_type == 15); Uint16 sound_id = in->read_u16(); sound_sample* sam = m->get_sound_sample(sound_id); if (sam) { start_sound_tag* sst = new start_sound_tag(); sst->read(in, tag_type, m, sam); IF_VERBOSE_PARSE(log_msg("start_sound tag: id=%d, stop = %d, loop ct = %d\n", sound_id, int(sst->m_stop_playback), sst->m_loop_count)); } else { if (s_sound_handler) { log_error("start_sound_loader: sound_id %d is not defined\n", sound_id); } } }
gc_ptr<root> player::load_file(const char* infile) // Load the actual movie. { gc_ptr<gameswf::movie_definition> md = create_movie(infile); if (md == NULL) { fprintf(stderr, "error: can't create a movie from '%s'\n", infile); return NULL; } gc_ptr<gameswf::root> m = md->create_instance(); if (m == NULL) { fprintf(stderr, "error: can't create movie instance\n"); return NULL; } int movie_version = m->get_movie_version(); #ifdef _DEBUG log_msg("Playing %s, swf version %d\n", infile, movie_version); #else IF_VERBOSE_PARSE(log_msg("Playing %s, swf version %d\n", infile, movie_version)); #endif return m; }
// instance_info // { // u30 name // u30 super_name // u8 flags // u30 protectedNs // u30 intrf_count // u30 interface[intrf_count] // u30 iinit // u30 trait_count // traits_info trait[trait_count] // } void instance_info::read(stream* in, abc_def* abc) { m_abc = abc; m_name = in->read_vu30(); m_super_name = in->read_vu30(); m_flags = in->read_u8(); if (m_flags & CONSTANT_ClassProtectedNs) { m_protectedNs = in->read_vu30(); } int i, n; n = in->read_vu30(); m_interface.resize(n); for (i = 0; i < n; i++) { m_interface[i] = in->read_vu30(); } m_iinit = in->read_vu30(); IF_VERBOSE_PARSE(log_msg(" name='%s', supername='%s', ns='%s'\n", abc->get_multiname(m_name), abc->get_multiname(m_super_name), abc->get_namespace(m_protectedNs))); n = in->read_vu30(); m_trait.resize(n); for (i = 0; i < n; i++) { traits_info* trait = new traits_info(); trait->read(in, abc); m_trait[i] = trait; } }
void font::read(stream* in, int tag_type, movie_definition_sub* m) { assert(tag_type == 10 || tag_type == 48 || tag_type == 75); // No add_ref() here, to avoid cycle. m_owning_movie is our owner, so it has a ref to us. m_owning_movie = m; if (tag_type == 10) { IF_VERBOSE_PARSE(log_msg("reading DefineFont\n")); int table_base = in->get_position(); // Read the glyph offsets. Offsets // are measured from the start of the // offset table. array<int> offsets; offsets.push_back(in->read_u16()); IF_VERBOSE_PARSE(log_msg("offset[0] = %d\n", offsets[0])); int count = offsets[0] >> 1; for (int i = 1; i < count; i++) { offsets.push_back(in->read_u16()); IF_VERBOSE_PARSE(log_msg("offset[%d] = %d\n", i, offsets[i])); } m_glyphs.resize(count); if (m->get_create_font_shapes() == DO_LOAD_FONT_SHAPES) { // Read the glyph shapes. {for (int i = 0; i < count; i++) { // Seek to the start of the shape data. int new_pos = table_base + offsets[i]; in->set_position(new_pos); // Create & read the shape. shape_character_def* s = new shape_character_def(m->get_player()); s->read(in, 2, false, m); m_glyphs[i] = s; }} } }
void as_3_function::read_body ( stream *in ) // read body_info { IF_VERBOSE_PARSE ( log_msg ( "body_info[%d]\n", m_method ) ); m_max_stack = in->read_vu30(); m_local_count = in->read_vu30(); m_init_scope_depth = in->read_vu30(); m_max_scope_depth = in->read_vu30(); int i, n; n = in->read_vu30(); // code_length m_code.resize ( n ); for ( i = 0; i < n; i++ ) { m_code[i] = in->read_u8(); } n = in->read_vu30(); // exception_count m_exception.resize ( n ); for ( i = 0; i < n; i++ ) { except_info *e = new except_info(); e->read ( in, m_abc.get_ptr() ); m_exception[i] = e; } n = in->read_vu30(); // trait_count m_trait.resize ( n ); for ( int i = 0; i < n; i++ ) { traits_info *trait = new traits_info(); trait->read ( in, m_abc.get_ptr() ); m_trait[i] = trait; } IF_VERBOSE_PARSE ( log_msg ( "method %i\n", m_method ) ); IF_VERBOSE_PARSE ( log_disasm_avm2 ( m_code, m_abc.get_ptr() ) ); }
void sprite_definition::read(stream* in) // Read the sprite info. Consists of a series of tags. { int tag_end = in->get_tag_end_position(); set_frame_count(in->read_u16()); m_playlist.resize(get_frame_count()); // need a playlist for each frame IF_VERBOSE_PARSE(log_msg(" frames = %d\n", get_frame_count())); while ((Uint32) in->get_position() < (Uint32) tag_end && get_break_loading() == false) { int tag_type = in->open_tag(); loader_function lf = NULL; if (tag_type == 1) { // show frame tag -- advance to the next frame. IF_VERBOSE_PARSE(log_msg(" show_frame (sprite)\n")); inc_loading_frame(); } else if (get_tag_loader(tag_type, &lf)) { // call the tag loader. The tag loader should add // characters or tags to the movie data structure. (*lf)(in, tag_type, this); } else { // no tag loader for this tag type. log_msg("*** no tag loader for type %d\n", tag_type); } in->close_tag(); } IF_VERBOSE_PARSE(log_msg(" -- sprite END --\n")); }
void morph2_character_def::read(stream* in, int tag_type, bool with_style, movie_definition_sub* md) { UNUSED(with_style); rect bound1, bound2; bound1.read(in); bound2.read(in); m_shape1->set_bound(bound1); m_shape2->set_bound(bound2); if(tag_type == 84) { rect edge_bound1, edge_bound2; edge_bound1.read(in); edge_bound2.read(in); int reserved = in->read_uint(6); assert(reserved == 0); m_uses_nonscaling_strokes = in->read_uint(1) == 1; m_uses_scaling_strokes = in->read_uint(1) == 1; } m_offset = in->read_u32(); m_fill_style_count = in->read_variable_count(); int i; for (i = 0; i < m_fill_style_count; i++) { fill_style fs1, fs2; fs1.m_type = in->read_u8(); fs2.m_type = fs1.m_type; IF_VERBOSE_PARSE(log_msg("morph fill style type = 0x%X\n", fs1.m_type)); if (fs1.m_type == 0x00) { fs1.m_color.read_rgba(in); fs2.m_color.read_rgba(in); IF_VERBOSE_PARSE(log_msg("morph fill style begin color: "); fs1.m_color.print()); IF_VERBOSE_PARSE(log_msg("morph fill style end color: "); fs2.m_color.print()); } else if (fs1.m_type == 0x10 || fs1.m_type == 0x12)
void as_3_function::read ( stream *in ) // read method_info { int param_count = in->read_vu30(); // The return_type field is an index into the multiname m_return_type = in->read_vu30(); m_param_type.resize ( param_count ); for ( int i = 0; i < param_count; i++ ) { m_param_type[i] = in->read_vu30(); } m_name = in->read_vu30(); m_flags = in->read_u8(); if ( m_flags & HAS_OPTIONAL ) { int option_count = in->read_vu30(); m_options.resize ( option_count ); for ( int o = 0; o < option_count; ++o ) { m_options[o].m_value = in->read_vu30(); m_options[o].m_kind = in->read_u8(); } } if ( m_flags & HAS_PARAM_NAMES ) { assert ( 0 && "todo" ); // param_info param_names } IF_VERBOSE_PARSE ( log_msg ( "method_info: name='%s', type='%s', params=%d\n", m_abc->get_string ( m_name ), m_abc->get_multiname ( m_return_type ), m_param_type.size() ) ); }
int gameswf::tools::process_swf(tu_file* swf_out, tu_file* in, const process_options& options) { assert(in && in->get_error() == TU_FILE_NO_ERROR); assert(swf_out && swf_out->get_error() == TU_FILE_NO_ERROR); // @@ Copied & adapted from movie_def_impl::read() // @@ TODO share this wrapper code somehow (also with gameswf_parser) Uint32 file_start_pos = in->get_position(); Uint32 header = in->read_le32(); Uint32 file_length = in->read_le32(); Uint32 file_end_pos = file_start_pos + file_length; int version = (header >> 24) & 255; if ((header & 0x0FFFFFF) != 0x00535746 && (header & 0x0FFFFFF) != 0x00535743) { // ERROR log_error("gameswf::movie_def_impl::read() -- file does not start with a SWF header!\n"); return 1; } bool compressed = (header & 255) == 'C'; IF_VERBOSE_PARSE(log_msg("version = %d, file_length = %d\n", version, file_length)); tu_file* original_in = NULL; if (compressed) { #if TU_CONFIG_LINK_TO_ZLIB == 0 log_error("gameswf can't read zipped SWF data; TU_CONFIG_LINK_TO_ZLIB is 0!\n"); return -1; #endif IF_VERBOSE_PARSE(log_msg("file is compressed.\n")); original_in = in; // Uncompress the input as we read it. in = zlib_adapter::make_inflater(original_in); // Subtract the size of the 8-byte header, since // it's not included in the compressed // stream length. file_end_pos = file_length - 8; } lfl_stream str(in); if (options.m_zip_whole_file) { // @@ TODO not implemented yet. log_error("gameswf::tools::process_swf(): options.m_zip_whole_file is not implemented! Output will not be zipped.\n"); } // // Start the output file // int output_file_start_pos = swf_out->get_position(); swf_out->write_le32(0x06535746); // Flash 6 header, uncompressed // File length (need to overwrite later with the actual value. int output_file_length_pos = swf_out->get_position(); swf_out->write_le32(0); float frame_rate = 30.f; int frame_count = 0; { copy_helper cp(in, swf_out); // copies everything that's read in this scope. rect dummy_frame_size; dummy_frame_size.read(&str); frame_rate = str.read_u16() / 256.0f; frame_count = str.read_u16(); str.align(); bool success = cp.do_copy(); if (!success) { // Error! log_error("gameswf::tools::process_swf() -- unable to copy header data!\n"); return 1; } } // m_playlist.resize(m_frame_count); // IF_VERBOSE_PARSE(m_frame_size.print()); IF_VERBOSE_PARSE(log_msg("frame rate = %f, frames = %d\n", frame_rate, frame_count)); while ((Uint32) str.get_position() < file_end_pos) { copy_helper cp(in, swf_out); int tag_type = str.open_tag(); if (options.m_remove_image_data && tag_type == 8) { // Don't need no stinkin jpeg tables. str.close_tag(); } else if (options.m_remove_image_data && (tag_type == 6 || tag_type == 20 || tag_type == 21 || tag_type == 35 || tag_type == 36)) { // Some type of bitmap character tag; replace it with a minimal stand-in. Uint16 cid = str.read_u16(); str.close_tag(); // Insert substitute tag. write_placeholder_bitmap(swf_out, cid); } else { // Leave this tag as-is. str.close_tag(); str.align(); // Copy into output. bool success = cp.do_copy(); if (!success) { // Error! log_error("gameswf::tools::process_swf() -- error copying tag!\n"); return 1; } } if (tag_type == 0) { if ((unsigned int) str.get_position() != file_end_pos) { // Safety break, so we don't read past the end of the // movie. log_msg("warning: process_swf() hit stream-end tag, but not at the " "end of the file yet; stopping for safety\n"); break; } } } if (original_in) { // Done with the zlib_adapter. delete in; } // Go back and write the file size. int current_pos = swf_out->get_position(); swf_out->set_position(output_file_length_pos); swf_out->write_le32(current_pos - output_file_start_pos); swf_out->set_position(current_pos); return 0; // OK }
bool SWFParser::read(std::streamsize bytes) { // If we didn't use all the bytes given to us last time, // we may read more than the size passed. _endRead += bytes; const SWF::TagLoadersTable& tagLoaders = _runResources.tagLoaders(); while (_bytesRead < _endRead) { const size_t startPos = _stream.tell(); // If a tag hasn't been opened, open one and check // how many bytes are needed. The size reported by the // tag seems to be the value used, even when it's wrong. if (!_tagOpen) { _nextTagEnd = openTag() - startPos; } try { // Check if we are now supposed to read enough bytes to get to the // end of the tag. if (_nextTagEnd > _endRead) { return true; } // Signal that we have reached the end of a SWF or sprite when // a SWF::END tag is encountered. if (_tag == SWF::END) { closeTag(); return false; } SWF::TagLoadersTable::TagLoader lf = nullptr; if (_tag == SWF::SHOWFRAME) { // show frame tag -- advance to the next frame. IF_VERBOSE_PARSE(log_parse(_("SHOWFRAME tag"))); _md->incrementLoadedFrames(); } else if (tagLoaders.get(_tag, lf)) { // call the tag loader. The tag loader should add // DisplayObjects or tags to the movie data structure. lf(_stream, _tag, *_md, _runResources); } else { // no tag loader for this tag type. log_error(_("Encountered unknown tag %d. These usually store " "creation tool data and do not affect playback"), _tag); IF_VERBOSE_PARSE( std::ostringstream ss; dumpTagBytes(_stream, ss); log_error(_("tag dump follows: %s"), ss.str()); ); } } catch (const ParserException& e) { // If the error occurred in a tag, we continue parsing so that // single malformed tags don't prevent reading subsequent tags. log_error(_("Parsing exception: %s"), e.what()); } if (_tagOpen) closeTag(); _bytesRead += (_stream.tell() - startPos); } return true; }
movie_definition* player::create_movie(const char* filename) { assert(filename); // Is the movie already in the library? if (s_use_cached_movie_def) { gc_ptr<character_def> m; get_chardef_library()->get(filename, &m); if (m != NULL) { // Return cached movie. return cast_to<movie_definition>(m.get_ptr()); } } if (s_opener_function == NULL) { // Don't even have a way to open the file. log_error("error: no file opener function; can't create movie. " "See gameswf::register_file_opener_callback\n"); return NULL; } tu_file* in = s_opener_function(filename); if (in == NULL) { log_error("failed to open '%s'; can't create movie.\n", filename); return NULL; } else if (in->get_error()) { log_error("error: file opener can't open '%s'\n", filename); delete in; return NULL; } ensure_loaders_registered(); movie_def_impl* m = new movie_def_impl(this, DO_LOAD_BITMAPS, DO_LOAD_FONT_SHAPES); if (s_use_cached_movie_def) { get_chardef_library()->add(filename, m); } m->read(in); // "in" will be deleted after termination of the loader thread // delete in; if (m && s_use_cache_files) { // Try to load a .gsc file. tu_string cache_filename(filename); cache_filename += ".gsc"; tu_file* cache_in = s_opener_function(cache_filename.c_str()); if (cache_in == NULL || cache_in->get_error() != TU_FILE_NO_ERROR) { // Can't open cache file; don't sweat it. IF_VERBOSE_PARSE(log_msg("note: couldn't open cache file '%s'\n", cache_filename.c_str())); } else { // Load the cached data. m->input_cached_data(cache_in); } delete cache_in; } return m; }
void read_filter_list( stream* in ) { // reads FILTERLIST int filters = in->read_u8(); for (int i = 0; i < filters; i++) { int filter_id = in->read_u8(); switch (filter_id) { case 0 : // DropShadowFilter { rgba drop_shadow_color; drop_shadow_color.read_rgba(in); // RGBA Color of the shadow float blur_x = in->read_fixed(); // Horizontal blur amount float blur_y = in->read_fixed(); // Vertical blur amount float angle = in->read_fixed(); // Radian angle of the drop shadow float distance = in->read_fixed(); // Distance of the drop shadow float strength = in->read_s8(); // hack, must be FIXED8 Strength of the drop shadow bool inner_shadow = in->read_bool(); // Inner shadow mode bool knockout = in->read_bool(); // Knockout mode bool composite_source = in->read_bool(); // Composite source Always 1 int passes = in->read_uint(5); // passes in->read_u8();// If not present, when parsing several filters, filter type is not correct IF_VERBOSE_PARSE(log_msg(" filter = DropShadowFilter\n" )); UNUSED(blur_x); UNUSED(blur_y); UNUSED(angle); UNUSED(distance); UNUSED(strength); UNUSED(inner_shadow); UNUSED(knockout); UNUSED(composite_source); UNUSED(passes); break; } case 1 : // BlurFilter { float blur_x = in->read_fixed(); // Horizontal blur amount float blur_y = in->read_fixed(); // Vertical blur amount int passes = in->read_uint(5); // Number of blur passes in->read_uint(3); // Reserved UB[3] Must be 0 IF_VERBOSE_PARSE(log_msg(" filter = BlurFilter\n" )); UNUSED(blur_x); UNUSED(blur_y); UNUSED(passes); break; } case 2 : // GlowFilter { rgba glow_color; glow_color.read_rgba(in); //RGBA Color of the shadow float blur_x = in->read_fixed(); // Horizontal blur amount float blur_y = in->read_fixed(); // Vertical blur amount float strength = in->read_s8(); // hack, must be FIXED8 Strength of the drop shadow bool inner_glow = in->read_bool(); // Inner glow mode bool knockout = in->read_bool(); // Knockout mode bool composite_source = in->read_bool(); // Composite source Always 1 in->read_uint(5); // passes in->read_u8();// If not present, when parsing several filters, filter type is not correct IF_VERBOSE_PARSE(log_msg(" filter = GlowFilter\n" )); UNUSED(blur_x); UNUSED(blur_y); UNUSED(strength); UNUSED(inner_glow); UNUSED(knockout); UNUSED(composite_source); break; } case 3 : // BevelFilter { rgba shadow_color; shadow_color.read_rgba(in); //RGBA Color of the shadow rgba highlight_color; highlight_color.read_rgba(in); //RGBA Color of the highlight float blur_x = in->read_fixed(); // Horizontal blur amount float blur_y = in->read_fixed(); // Vertical blur amount float angle = in->read_fixed(); // Radian angle of the drop shadow float distance = in->read_fixed(); // Distance of the drop shadow float strength = in->read_s8(); // hack, must be FIXED8 Strength of the drop shadow bool inner_shadow = in->read_bool(); // Inner shadow mode bool knockout = in->read_bool(); // Knockout mode bool composite_source = in->read_bool(); // Composite source Always 1 bool on_top = in->read_bool(); // Composite source Always 1 int passes = in->read_uint(4); // passes in->read_u8();// If not present, when parsing several filters, filter type is not correct IF_VERBOSE_PARSE(log_msg(" filter = BevelFilter\n" )); UNUSED(blur_x); UNUSED(blur_y); UNUSED(angle); UNUSED(distance); UNUSED(strength); UNUSED(inner_shadow); UNUSED(knockout); UNUSED(composite_source); UNUSED(on_top); UNUSED(passes); break; } case 4 : // GradientGlowFilter { int num_colors = in->read_u8(); // Number of colors in the gradient for (int i = 0; i < num_colors; i++) { rgba gradient_colors; gradient_colors.read_rgba(in); // RGBA[NumColors] Gradient colors } for (int i = 0; i < num_colors; i++) { int gradient_ratio = in->read_u8(); // UI8[NumColors] Gradient ratios UNUSED(gradient_ratio); } float blur_x = in->read_fixed(); // Horizontal blur amount float blur_y = in->read_fixed(); // Vertical blur amount float angle = in->read_fixed(); // Radian angle of the drop shadow float distance = in->read_fixed(); // Distance of the drop shadow float strength = in->read_s8(); // hack, must be FIXED8 Strength of the drop shadow bool inner_shadow = in->read_bool(); // Inner shadow mode bool knockout = in->read_bool(); // Knockout mode bool composite_source = in->read_bool(); // Composite source Always 1 bool on_top = in->read_bool(); // Composite source Always 1 int passes = in->read_uint(4); // passes UNUSED(blur_x); UNUSED(blur_y); UNUSED(angle); UNUSED(distance); UNUSED(strength); UNUSED(inner_shadow); UNUSED(knockout); UNUSED(composite_source); UNUSED(on_top); UNUSED(passes); IF_VERBOSE_PARSE(log_msg(" filter = GradientGlowFilter\n" )); break; } case 5 : // ConvolutionFilter { int matrix_x = in->read_u8(); // Horizontal matrix size int matrix_y = in->read_u8(); // Vertical matrix size float divisor = in->read_float(); // Divisor applied to the matrix values float bias = in->read_float(); // Bias applied to the matrix values for (int k = 0; k < matrix_x * matrix_y; k++) { in->read_float(); // Matrix values } rgba default_color; default_color.read_rgba(in); // RGBA Default color for pixels outside the image in->read_uint(6); // Reserved UB[6] Must be 0 bool clamp = in->read_bool(); // UB[1] Clamp mode bool preserve_alpha = in->read_bool(); // UB[1] IF_VERBOSE_PARSE(log_msg(" filter = ConvolutionFilter\n" )); UNUSED(divisor); UNUSED(bias); UNUSED(clamp); UNUSED(preserve_alpha); break; } case 6 : // ColorMatrixFilter // matrix is float[20] for (int k = 0; k < 20; k++) { in->read_float(); } IF_VERBOSE_PARSE(log_msg(" filter = ColorMatrixFilter\n" )); break; case 7 : // GradientBevelFilter { int num_colors = in->read_u8(); // Number of colors in the gradient for (int i = 0; i < num_colors; i++) { rgba gradient_colors; gradient_colors.read_rgba(in); // RGBA[NumColors] Gradient colors } for (int i = 0; i < num_colors; i++) { int gradient_ratio = in->read_u8(); // UI8[NumColors] Gradient ratios UNUSED(gradient_ratio); } float blur_x = in->read_fixed(); // Horizontal blur amount float blur_y = in->read_fixed(); // Vertical blur amount float angle = in->read_fixed(); // Radian angle of the drop shadow float distance = in->read_fixed(); // Distance of the drop shadow float strength = in->read_s8(); // hack, must be FIXED8 Strength of the drop shadow bool inner_shadow = in->read_bool(); // Inner shadow mode bool knockout = in->read_bool(); // Knockout mode bool composite_source = in->read_bool(); // Composite source Always 1 bool on_top = in->read_bool(); // Composite source Always 1 int passes = in->read_uint(4); // passes in->read_u8();// If not present, when parsing several filters, filter type is not correct IF_VERBOSE_PARSE(log_msg(" filter = GradientBevelFilter\n" )); UNUSED(blur_x); UNUSED(blur_y); UNUSED(angle); UNUSED(distance); UNUSED(strength); UNUSED(inner_shadow); UNUSED(knockout); UNUSED(composite_source); UNUSED(on_top); UNUSED(passes); break; } default: assert(0); // invalid input } } }
// cpool_info // { // u30 int_count // s32 integer[int_count] // u30 uint_count // u32 uinteger[uint_count] // u30 double_count // d64 double[double_count] // u30 string_count // string_info string[string_count] // u30 namespace_count // namespace_info namespace[namespace_count] // u30 ns_set_count // ns_set_info ns_set[ns_set_count] // u30 multiname_count // multiname_info multiname[multiname_count] // } void abc_def::read_cpool(stream* in) { int n; // integer pool n = in->read_vu30(); if (n > 0) { m_integer.resize(n); m_integer[0] = 0; // default value for (int i = 1; i < n; i++) { m_integer[i] = in->read_vs32(); IF_VERBOSE_PARSE(log_msg("cpool_info: integer[%d]=%d\n", i, m_integer[i])); } } else { IF_VERBOSE_PARSE(log_msg("cpool_info: no integer pool\n")); } // uinteger pool n = in->read_vu30(); if (n > 0) { m_uinteger.resize(n); m_uinteger[0] = 0; // default value for (int i = 1; i < n; i++) { m_uinteger[i] = in->read_vu32(); IF_VERBOSE_PARSE(log_msg("cpool_info: uinteger[%d]=%d\n", i, m_uinteger[i])); } } else { IF_VERBOSE_PARSE(log_msg("cpool_info: no uinteger pool\n")); } // double pool n = in->read_vu30(); if (n > 0) { m_double.resize(n); m_double[0] = 0; // default value for (int i = 1; i < n; i++) { m_double[i] = in->read_double(); IF_VERBOSE_PARSE(log_msg("cpool_info: double[%d]=%f\n", i, m_double[i])); } } else { IF_VERBOSE_PARSE(log_msg("cpool_info: no double pool\n")); } // string pool n = in->read_vu30(); if (n > 0) { m_string.resize(n); m_string[0] = ""; // default value for (int i = 1; i < n; i++) { int len = in->read_vs32(); in->read_string_with_length(len, &m_string[i]); IF_VERBOSE_PARSE(log_msg("cpool_info: string[%d]='%s'\n", i, m_string[i].c_str())); } } else { IF_VERBOSE_PARSE(log_msg("cpool_info: no string pool\n")); } // namespace pool n = in->read_vu30(); if (n > 0) { m_namespace.resize(n); namespac ns; m_namespace[0] = ns; // default value for (int i = 1; i < n; i++) { ns.m_kind = static_cast<namespac::kind>(in->read_u8()); ns.m_name = in->read_vu30(); m_namespace[i] = ns; // User-defined namespaces have kind CONSTANT_Namespace or // CONSTANT_ExplicitNamespace and a non-empty name. // System namespaces have empty names and one of the other kinds switch (ns.m_kind) { case namespac::CONSTANT_Namespace: case namespac::CONSTANT_ExplicitNamespace: //assert(*get_string(ns.m_name) != 0); break; case namespac::CONSTANT_PackageNamespace: case namespac::CONSTANT_PackageInternalNs: case namespac::CONSTANT_ProtectedNamespace: case namespac::CONSTANT_StaticProtectedNs: case namespac::CONSTANT_PrivateNs: //assert(*get_string(ns.m_name) == 0); break; default: assert(0); } IF_VERBOSE_PARSE(log_msg("cpool_info: namespace[%d]='%s', kind=0x%02X\n", i, get_string(ns.m_name), ns.m_kind)); } } else { IF_VERBOSE_PARSE(log_msg("cpool_info: no namespace pool\n")); } // namespace sets pool n = in->read_vu30(); if (n > 0) { m_ns_set.resize(n); swf_array<int> ns; m_ns_set[0] = ns; // default value for (int i = 1; i < n; i++) { int count = in->read_vu30(); ns.resize(count); for (int j = 0; j < count; j++) { ns[j] = in->read_vu30(); } m_ns_set[i] = ns; } } else { IF_VERBOSE_PARSE(log_msg("cpool_info: no namespace sets\n")); } // multiname pool n = in->read_vu30(); if (n > 0) { m_multiname.resize(n); multiname mn; m_multiname[0] = mn; // default value for (int i = 1; i < n; i++) { Uint8 kind = in->read_u8(); mn.m_kind = kind; switch (kind) { case multiname::CONSTANT_QName: case multiname::CONSTANT_QNameA: { mn.m_ns = in->read_vu30(); mn.m_name = in->read_vu30(); IF_VERBOSE_PARSE(log_msg("cpool_info: multiname[%d]='%s', ns='%s'\n", i, get_string(mn.m_name), get_namespace(mn.m_ns))); break; } case multiname::CONSTANT_RTQName: assert(0&&"todo"); break; case multiname::CONSTANT_RTQNameA: assert(0&&"todo"); break; case multiname::CONSTANT_RTQNameL: assert(0&&"todo"); break; case multiname::CONSTANT_RTQNameLA: assert(0&&"todo"); break; case multiname::CONSTANT_Multiname: case multiname::CONSTANT_MultinameA: mn.m_name = in->read_vu30(); mn.m_ns_set = in->read_vu30(); IF_VERBOSE_PARSE(log_msg("cpool_info: multiname[%d]='%s', ns_set='%s'\n", i, get_string(mn.m_name), "todo")); break; case multiname::CONSTANT_MultinameL: case multiname::CONSTANT_MultinameLA: mn.m_ns_set = in->read_vu30(); mn.m_name = -1; IF_VERBOSE_PARSE(log_msg("cpool_info: multiname[%d]=MultinameL, ns_set='%s'\n", i, "todo")); break; default: assert(0); } m_multiname[i] = mn; } } else { IF_VERBOSE_PARSE(log_msg("cpool_info: no multiname pool\n")); } }
std::auto_ptr<EncodedVideoFrame> FLVParser::parseVideoTag(const FLVTag& flvtag, const FLVVideoTag& videotag, boost::uint32_t thisTagPos) { if ( ! _video ) { log_error(_("Unexpected video tag found at offset %d of FLV stream " "advertising no video in header. We'll warn only once per " "FLV, expecting any further video tag."), thisTagPos); _video = true; // TOCHECK: is this safe ? } bool header = false; boost::uint32_t bodyLength = flvtag.body_size; switch(videotag.codec) { case VIDEO_CODEC_VP6: case VIDEO_CODEC_VP6A: { _stream->read_byte(); --bodyLength; break; } case VIDEO_CODEC_H264: { boost::uint8_t packettype = _stream->read_byte(); IF_VERBOSE_PARSE( log_debug(_("AVC packet type: %d"), (unsigned)packettype) ); header = (packettype == 0); // 24-bits value for composition time offset ignored for now. boost::uint8_t tmp[3]; _stream->read(tmp, 3); bodyLength -= 4; break; } default: break; } std::auto_ptr<EncodedVideoFrame> frame = readVideoFrame(bodyLength-1, flvtag.timestamp); if ( ! frame.get() ) { log_error(_("could not read video frame?")); } // If this is the first videoframe no info about the // video format has been noted, so we do that now if ( ! _videoInfo.get() ) { _videoInfo.reset(new VideoInfo(videotag.codec, 0, 0, 0, 0, CODEC_TYPE_FLASH)); if (header) { // The frame is 0-padded up to the end. It may be larger than // this if fewer bytes were read than requested, but it is // never smaller. const size_t bufSize = frame->dataSize() + paddingBytes; boost::uint8_t* data = new boost::uint8_t[bufSize]; std::copy(frame->data(), frame->data() + bufSize, data); _videoInfo->extra.reset( new ExtraVideoInfoFlv(data, frame->dataSize()) ); // Don't bother emitting the header buffer. frame.reset(); } } return frame; }
// abcFile // { // u16 minor_version // u16 major_version // cpool_info cpool_info // u30 method_count // method_info method[method_count] // u30 metadata_count // metadata_info metadata[metadata_count] // u30 class_count // instance_info instance[class_count] // class_info class[class_count] // u30 script_count // script_info script[script_count] // u30 method_body_count // method_body_info method_body[method_body_count] // } void abc_def::read(stream* in, movie_definition_sub* m) { int eof = in->get_tag_end_position(); int i, n; Uint16 minor_version = in->read_u16(); Uint16 major_version = in->read_u16(); assert(minor_version == 16 && major_version == 46); // read constant pool read_cpool(in); assert(in->get_position() < eof); // read method_info n = in->read_vu30(); m_method.resize(n); IF_VERBOSE_PARSE(log_msg("method_info count: %d\n", n)); for (i = 0; i < n; i++) { as_3_function* info = new as_3_function(this, i, m->get_player()); info->read(in); m_method[i] = info; } assert(in->get_position() < eof); // read metadata_info n = in->read_vu30(); m_metadata.resize(n); IF_VERBOSE_PARSE(log_msg("metadata_info count: %d\n", n)); for (i = 0; i < n; i++) { assert(0 && "test"); metadata_info* info = new metadata_info(); info->read(in, this); m_metadata[i] = info; } assert(in->get_position() < eof); // read instance_info & class_info n = in->read_vu30(); m_instance.resize(n); IF_VERBOSE_PARSE(log_msg("instance_info count: %d\n", n)); for (i = 0; i < n; i++) { IF_VERBOSE_PARSE(log_msg("instance_info[%d]:\n", i)); instance_info* info = new instance_info(); info->read(in, this); m_instance[i] = info; } assert(in->get_position() < eof); // class_info m_class.resize(n); IF_VERBOSE_PARSE(log_msg("class_info count: %d\n", n)); for (i = 0; i < n; i++) { IF_VERBOSE_PARSE(log_msg("class_info[%d]\n", i)); class_info* info = new class_info(); info->read(in, this); m_class[i] = info; } assert(in->get_position() < eof); // read script_info n = in->read_vu30(); m_script.resize(n); IF_VERBOSE_PARSE(log_msg("script_info count: %d\n", n)); for (i = 0; i < n; i++) { IF_VERBOSE_PARSE(log_msg("script_info[%d]\n", i)); script_info* info = new script_info(); info->read(in, this); m_script[i] = info; } assert(in->get_position() < eof); // read body_info n = in->read_vu30(); for (i = 0; i < n; i++) { int method_index = in->read_vu30(); m_method[method_index]->read_body(in); } assert(in->get_position() == eof); }
void define_sound_loader(stream* in, int tag_type, movie_definition_sub* m) // Load a DefineSound tag. { assert(tag_type == 14); Uint16 character_id = in->read_u16(); sound_handler::format_type format = (sound_handler::format_type) in->read_uint(4); int sample_rate = in->read_uint(2); // multiples of 5512.5 bool sample_16bit = in->read_uint(1) ? true : false; bool stereo = in->read_uint(1) ? true : false; int sample_count = in->read_u32(); IF_VERBOSE_PARSE(log_msg("define sound: ch=%d, format=%d, rate=%d, 16=%d, stereo=%d, ct=%d\n", character_id, int(format), sample_rate, int(sample_16bit), int(stereo), sample_count)); // If we have a sound_handler, ask it to init this sound. if (s_sound_handler) { int data_bytes = 0; unsigned char* data = NULL; if (format == sound_handler::FORMAT_ADPCM) { // Uncompress the ADPCM before handing data to host. data_bytes = sample_count * (stereo ? 4 : 2); data = new unsigned char[data_bytes]; adpcm_expand(data, in, sample_count, stereo); format = sound_handler::FORMAT_NATIVE16; } else { // @@ This is pretty awful -- lots of copying, slow reading. data_bytes = in->get_tag_end_position() - in->get_position(); data = new unsigned char[data_bytes]; for (int i = 0; i < data_bytes; i++) { data[i] = in->read_u8(); } // Swap bytes on behalf of the host, to make it easier for the handler. // @@ I'm assuming this is a good idea? Most sound handlers will prefer native endianness? if (format == sound_handler::FORMAT_UNCOMPRESSED && sample_16bit) { #ifndef _TU_LITTLE_ENDIAN_ // Swap sample bytes to get big-endian format. for (int i = 0; i < data_bytes - 1; i += 2) { swap(&data[i], &data[i+1]); } #endif // not _TU_LITTLE_ENDIAN_ format = sound_handler::FORMAT_NATIVE16; } } int handler_id = s_sound_handler->create_sound( data, data_bytes, sample_count, format, get_sample_rate(sample_rate), stereo); sound_sample* sam = new sound_sample(m->get_player(), handler_id); m->add_sound_sample(character_id, sam); delete [] data; } }
// traits_info // { // u30 name // u8 kind // u8 data[] // u30 metadata_count // u30 metadata[metadata_count] // } void traits_info::read(stream* in, abc_def* abc) { // The value can not be zero, and the multiname entry specified must be a QName. m_name = in->read_vu30(); assert(m_name != 0 && abc->m_multiname[m_name].is_qname()); IF_VERBOSE_PARSE(log_msg(" traits: name='%s'\n", abc->get_multiname(m_name))); Uint8 b = in->read_u8(); m_kind = b & 0x0F; m_attr = b >> 4; switch (m_kind) { case Trait_Slot : case Trait_Const : trait_slot.m_slot_id = in->read_vu30(); trait_slot.m_type_name = in->read_vu30(); assert(trait_slot.m_type_name < abc->m_multiname.size()); trait_slot.m_vindex = in->read_vu30(); if (trait_slot.m_vindex != 0) { // This field exists only when vindex is non-zero. trait_slot.m_vkind = in->read_u8(); } break; case Trait_Class : trait_class.m_slot_id = in->read_vu30(); trait_class.m_classi = in->read_vu30(); assert(trait_class.m_classi < abc->m_class.size()); break; case Trait_Function : trait_function.m_slot_id = in->read_vu30(); trait_function.m_function = in->read_vu30(); assert(trait_function.m_function < abc->m_method.size()); break; case Trait_Method : case Trait_Getter : case Trait_Setter : trait_method.m_disp_id = in->read_vu30(); trait_method.m_method = in->read_vu30(); assert(trait_method.m_method < abc->m_method.size()); break; default: assert(false && "invalid kind of traits"); break; } if (m_attr & ATTR_Metadata) { assert(0 && "test"); int n = in->read_vu30(); m_metadata.resize(n); for (int i = 0; i < n; i++) { m_metadata[i] = in->read_vu30(); } } }