SWF Loading

From Gnash Project Wiki

Jump to: navigation, search

Gnash loading/parsing of SWF needs some love.

For a start, see http://savannah.gnu.org/patch/index.php?6334


The problem

Problem with loading/parsing is performance.

The final parser routines are mostly users of the gnash::stream class, which wraps a tu_file of any flavor (different adapters imlemented for network access and compressed formats) adding some sort of tag boundaries checking on top of it and a bitwise reading abstraction.

Every read by the parser code is a function call to gnash::stream interface. In the best case the function returns some bits from the currently unused set (at most 8 bits) in its cache. In the worst case the function call the underlying tu_file interface to fill the cache, which involves at best 2 function calls (the tu_file one and the actual reader function stored in a tu_file). In the worst case, the tu_file reading function itself triggers read from other inputs, caching to temp outputs, caching to memory and finally returning the needed data. See below for more info.

Current data flow

Now, where the data goes depends on the stack of tu_file adapters engaged before reacing the gnash::stream level. In current head, gnash::stream doesn't perform any caching except for a single byte while doing bitwise reads.

For the lower level (tu_file) we have these implementations:

  • file stream : doesn't cache, uses underlying filesystem interface
  • noseek fd adapter : wraps a non-seekable stream (tipically STDIN) to provide seek back capabilities. In doing so it creates a temporary file that keep growing as you read from it, seek backs seeking on this filesystem cache.
  • curl adapter : wraps a network socket stream to provide seek-back capabilities. In doing so it creates a temporary file that keeps growing as you read from it, seek backs seeking on this filesystem cache.
  • zlib adapter : inflates the data fetched from an underlying tu_file in memory buffers of 4096 bytes, seek-back implemented by reinflating from scratch !!

Simplest case

The simplest setup is loading an uncompressed SWF from filesystem. In this case layers are:

  • [ filesystem tu_file ] ----> [ gnash::stream ] ----> parsing routines

There are no memory buffers here, except that single byte in gnash::stream

Most complex case

The most complex case is reading a compressed SWF from network or stdin. In this case layers are:

  • [ curl adapter ] ----> [ zlib adapter ] -----> [ gnash::stream ]
  • [ noseek adapter ] ---> [ zlib adapter ] ----> [ gnash::stream ]

Here we have data going from actual input to a filesystem cache, then from there to a memory buffer (zlib adapter) and finally from there to the gnash::stream. Seek backs going before start of memory buffer in zlib adapter triggering restart of the inflating process.