User:Rintarou Chou

From Gnash Project Wiki

Jump to: navigation, search

Contents

SWF Format Visualization

SWF Parser is written from scratch for better understanding only.

How it works?

1. SWF Parser : SWF -> JSON Object Format (The properties are ordered in SWF endian.)

2. HTML Version use JavaScript (one function only) to traverse JSON Object and show it in HTML Tables.

3. Flash Version would get the same JSON Object like HTML Version but show it's structure with easier understandable way.


Flash Version (SWFVisualizer)

HTML Version

Issues

These are just small self training projects (Just for fun), not for any specific purpose. Everything is written from scratch, only depends on stdc++ and zlib.

  • Metadata, DefineFont4, DoABC Tags are not supported yet.
  • ActionCode is not decoded yet.
  • Code quality is so bad.
  • No memory management.
  • No documentation.
  • No optimization.
  • Code will be modified anytime I want to try something.
  • Programming with XCode and not ported to other platforms yet.
  • Hosted in my own Mac at my home.



Scriptable Plugin

A small patch to support scriptable plugin.

Download

http://savannah.gnu.org/patch/?6821

Test page

plugin/scriptable-test.html

JavaScript can get embed[0].version now.


Todo

Implement the methods listed in the following URL should be supported.

http://www.adobe.com/support/flash/publishexport/scriptingwithflash/scriptingwithflash_03.html


Issues

Functionality

  • gtk-gnash did not support multiple instances yet.
    • 2 pipes(GIOChannel) to communicate between plugin and gtk-gnash.
    • p2c pipe : pass SWF file stream from plugin to gtk-gnash(make_stream())
    • c2p pipe : gtk-gnash ask plugin for GET/POST/FSCOMMAND.
  • gtk-gnash(VM) did not support async call yet.
    • Async requests from plugin or extension may cause gtk-gnash crashed.

Performance

  • GnashImage only support alpha, RGB888 and RGBA8888 pixel format.
    • Cairo did not support RGBA8888 pixel format, need conversion to ARGB8888 before sent to the renderer. So bad to performance.
    • Cairo may not be the fastest pure software renderer, but it had good extensibility for different hardware platforms. Platform specific optimizations are the key to performance for the low-end devices.
  • Cairo did not support quadratic bezier curve, need conversion to cubic bezier curve.

Thinkings

  • Work with the chip venders for platform specific optimizations.
    • Use PS3-Cell SPE for the renderer/matrix optimization.
    • Use SIMD instructions for the renderer/matrix optimization since most of the low-end devices had no hardware OpenGL support.
      • MMX/SSE[2/3]/AltiVec
  • OpenVG renderer
    • The open standard is always preferred.
  • Both ActionScript and JavaScript are ECMAScript(ECMA-262) implementations.
    • Adobe AIR proved the ActionScript and JavaScript bridge is possible, we should do this for both AS/JS programmers.
  • Why bother to be another solution when FlashPlayer is already free in PC market? But it's not free in the embedded systems. It would be our advantage in the embedded system market.
  • Pre-multiplied alpha would get a great performance improvement while pixel compositing.
    • Although there is a drawback of color space reduction, it should not be noticed in animations.


Hack Notes

Gnash Internal 0.8.5 (2009/04/25)

Full Chinese Version :

- Part 1 - Part 2

Directory Structure

Image:GnashHackNotesInternal-20090425.jpg

(Sorry! Not allowed to upload file yet.)

  • gnash::Player (Soul of Gnash)
    • gnash::gui : The GUI to get and response the user input events.
      • Renderer
      • movie_root : The stage
        • See movie_root::advance() for the pipe line to handle each frame.
    • gnash::VM : The virtual machine
    • parser/
      • MovieDefinition
        • SWFMovieDefinition
        • SpriteDefiniton
        • BitmapMovieDefinition
      • SoundDefinition
    • asobj/ : The built-in objects implementations.
  • Sub-systems
    • Log
    • Sound
    • Media
    • Net
    • Plugin

Initialization

  • Main Thread => Player::Run()
    • Init sub-systems
      • init_logfile()
      • init_media()
      • init_sound()
      • init_gui()
    • setup runInfo
    • load the actual movie => _movieDef = load_movie();
      • Plugin will send SWF stream by stdin, so create the stream from stdin. => std::auto_ptr<IOChannel> in ( noseek_fd_adapter::make_stream(fileno(stdin)));
      • create movie_definition => md = gnash::create_movie(in, _url, *_runInfo, false); // Should be renamed to create_movie_definition()??
        • Register all tag loader functions => ensure_loaders_registered();
        • return SWFMovieDefinition => return createSWFMovie(in, url, runInfo, startLoaderThread); // Should be renamed to createSWFMovieDefinition()??
          • new a SWFMovieDefiniton instance => std::auto_ptr<SWFMovieDefinition> m (new SWFMovieDefinition(runInfo));
          • read SWF header => if (!m->readHeader(in, absURL)) return 0;
          • start loader thread if needed. => if (startLoaderThread && !m->completeLoad()) return 0;
          • return the created SWFMovieDefinition instance => return m.release();
      • return movie_definition.
    • create a movie_root as the stage. => movie_root root(*_movieDef, _gui->getClock(), *_runInfo);
      • register event handlers to get movie_root's events.
    • start loader thread => _movieDef->completeLoad();
    • setup interval timer => _gui->setInterval(_delay);
    • pass gui to continue (get user events and trigger the timer to advance the movie) => _gui->run();
  • MovieLoader Thread
    • The loader thread will call read_all_swf() to parse SWFStream. => md->read_all_swf();
      • get tag type from stream => SWF::TagType tag = str.open_tag();
      • if tag == SWF::END then stop parsing. => break while loop.
      • if tag == SWF::SHOWFRAME then advance loaded frame. => size_t floaded = incrementLoadedFrames();
      • else get tag loader functions according tag type => _tag_loaders.get(tag, &lf);
        • call the tag loader function => lf(str, tag, *this, _runInfo);

Tag Loaders

  • Each tag is handled by corresponding tag loader (TagLoaderTable::loader_function)
    • Each Tag(both Definition Tags and Control Tags) defined a static loader function. (See libcore/swf/)
    • The loader function will create the corresponding tag instance once it's called.
    • The tag instance will parse the input stream(ex: SWFStream) to get the information to create corresponding data structures used later.
    • Definition Tags and Control Tags are working differently.
      • Definition Tags are going to create the characters to the dictionary.
      • Control Tags are placing or removing character instances to the display list.
        • Gnash treats ActionScript related tags as Control Tags.
  • All tag loaders are registered to the TagLoaderTable while initialization.
    • See imlp.cpp:ensure_loaders_registered()

as_object

  • as_object : To implement the ECMAScript Object.
    • Is a container with PropertyList.
    • Each Property is a (name, value) pair.
      • The value stored in the Property is as_value.
      • name is a string.
        • ex: var obj = new Object(); obj.foo = new Object(); => "foo" is the name of the Property owned by obj.
      • as_value is the primitive data defined in ECMAScript.
        • as_value can be transformed to AMF format.
      • AsType defined the data type that as_value is one of the following:
        • UNDEFINED : Undefined value. => boost::blank()
        • NULLTYPE : NULL value. => boost::blank()
        • BOOLEAN : Boolean value. => bool
        • STRING : String value. => std::string
        • NUMBER : Number value. => double
        • OBJECT : Object reference. => AsObjPtr (=boost::intrusive_ptr<as_object>)
          • This is how an object and contain other objects
        • AS_FUNCTION : ActionScript function reference. => AsFuncPtr (=boost::intrusive_ptr<as_function>)
        • MOVIECLIP : MovieClip reference. (Not defined in ECMAScript)

SWFMovieDefinition

  • _dictionary:CharacterDictionary is the dictionary to hold characters.
    • CharacterDictionary
      • _map : CharacterContainer
        • typedef std::map< int, boost::intrusive_ptr<SWF::DefinitionTag > > CharacterContainer

Each DefinitionTag will call addDisplayObject to add itself(instance) into the dictionary.

  • addDisplayObject(int id, SWF::DefinitionTag *c);
    • _dictionary.addDisplayObject(id, c);
      • _map[id] = c;

(Should addDisplayObject() be renamed to addDefinitionTag() or addCharacter()??)


Each ControlTag will call addControlTag() to add itself(instance) into the playlist of SWFMovieDefinition.

  • addControlTag(SWF::ControlTag *tag);
    • Add an ControlTag to this movie_definition's playlist.
    • m_playlist[_frames_loaded].push_back(tag);
  • createMovie(DisplayObject* parent);
    • return new SWFMovie(this, parent);

SWFMovie

SWFMovie extends Movie which extends MovieClip.

  • SWFMovie::SWFMovie(const SWFMovieDefinition* const def, DisplayObject* parent);
    • Movie(def, parent)
    • _def(def)


MovieClip

MovieClip is a DisplayObject with it's own timeline and it's DisplayList.


movie_root

The stage of the movie. But it's not a MovieClip.

(Why not just rename to Stage??)

  • movie_root constructor will set _vm(VM::init(def.get_version(), *this, clock))
    • _vm : VM
      • a sigleton get by VM::init();
        • return a sigleton instance of VM.
  • movie_root::advance();
    • advanceMovie();
    • executeAdvanceCallbacks();
    • executeTimers();
  • movie_root::setRootMovie(Movie *movie);
    • _rootMovie = movie;
    • processActionQueue();
  • _actionQueue:ActionQueue
  • Gui::start();
    • create movie => std::auto_ptr<Movie> mr ( _movieDef->createMovie() );
    • setRootMovie => _stage->setRootMovie(mr.release());
    • start virtual clock => _virtualClock.resume();

News

  • Broadcom, Intel and ARM joined the Open Screen Project and work with Adobe for Flash optimizations.


About

  • Rintarou Chou <shuho.chou@gmail.com>
  • Taiwanese (Sorry for my poor English!!)