Wednesday, October 29, 2008

SWF TimeLine

Flash player plays SWF by frames. This happens when flash player "meets" tagShowFrame, i.e. no changes in animation can be seen without this tag. Frame rate is specified in file title as FPS value. The summary duration of playing SWF can be calculated by multiplying the number of frames by FPS (Frames per Second) value.

This is theory, but in practice everything is much more difficult and that's why.

The matter is SWF can be not a simple movie, but a complicated logic script with interactivity elements. Frames can be changed in whatever sequence, including the one with stopping on a frame to wait user reaction. In fact, such SWFs are web applications.

Besides, in a movie, one can use special objects Sprites, in terms of Flash IDE they are called MovieClips. Sprites have the same structure as SWF (a set of tags) and their own timeline. There are SWFs with only one SWF frame where all the animation takes place in sprites.

And the last. Sometimes flash player can't prepare frame for playing in time. As a rule, this happens when there is a transformation of images or superposition of multiple masks in a frame. In this cases, frames are changed obviously more seldom than it's specified in FPS.


Conclusion. In most cases it's IMPOSSIBLE to determine duration of SWF. In most cases it's IMPOSSIBLE to scroll SWF for example to the third frame if you don't know movie structure and script. In most cases it's IMPOSSIBLE to know if an SWF finished playing, because "the action" can take place not in the main timeline, but in sprites.

Friday, October 24, 2008

Introduction. SWF structure.

I think everybody knows that awkward situation when you're asked a "wrong" question because the person who asks knows nothing about the topic. It's difficult to understand what to start answer from in such a situation. That's why I'll begin... at the very beginning.

Introduction

When saying Flash, we can mean absolutely different things even within the bounds of web-technology terms. Not to get confused, I'll use the following terms:

  • Flash – the technology of web-animation on the whole;
  • Flash player – program, ActiveX library which displays flash;
  • Standalone Flash player – application (exe file) displaying flash;
  • Flash IDE, Adobe Flash, Flash Professional – development environment provided by Adobe Systems (former Macromedia);
  • FLA – project (source) animation file for Flash IDE;
  • Movie – an integral web-animation at the development stage;
  • SWF – result animation file.
  • So, when loading a web page with flash animation, the following processes take place: web-browser detects an embedded flash animation in an HTML markup, creates and object of flash-player and indicate what file needs to be displayed. Flash player loads SWF file and begins to display it if possible. Due to this principle of work, flash player can display so called preloaders, reproduce streaming audio and video (for example, YouTube) without loading SWF fully.

    SWF structure

    File format is described in "SWF file format specification" document, which can be downloaded at Adobe.com. Documentation is usually issued some months after the release of a new version of flash player. At the moment, flash player v.10 is already released, but specification document is not renewed and contains specification of version 9. One can find specifications about almost everything I explain here, but the matter is that "almost", but not everything :)

    Basic structure of SWF doesn't depend on version, that's why SWF always has Header+Body structure. Body consists of records which are called tags in specification.

    To describe data structure, I'll use Object Pascal syntax.

    Header

    Header contains main information about SWF. It can be described in this way:

    TSWFHeader = packed record
    SIGN: array [0..2] of AnsiChar;
    Version: byte;
    FileSize: LongWord;
    MovieRect: TRect;
    FPS: word;
    FramesCount: word;
    end;

  • The first parameter is SIGN. CWS value means that this file is packed using ZLib compression method, not an FWS.
  • Version – version of file format.
  • FileSize – size of UNPACKED file in bytes.
  • MovieRect – size of displayed image in twips (1px = 20twips). I should note that in fact SWF and graphic objects can't be larger than $ffff/ 20 = 3276 px. I haven't seen swf with top-left value less or more than 0. Nevertheless, having set these values in my tests, I made sure that these values are really taken into account. It's worth noting that the specified rectangle is a place given by browser. When opening SWF in a standalone player, sometimes one can see "decorations behind the scenes".
  • FPS (frames per second) – value in format 8.8 fixed, i.e. for human perception this value is Result := FPS shr 8 + (FPS and $FF) / ($FF+1);
  • FramesCount– frames number. As a rule, SWF always has at least one frame, but it's possible to create SWF without frames if this file is used as a library for other SWFs.
  • SWF compression

    To reduce file size, Macromedia has used two approaches.

    The first one consists of that bit-by-bit compression method is used for saving numbers. It looks like this. Let's presume we need to save a size of rectangle, i.e. four numbers of integer type. At a simple record it will be 4 * 4 bytes = 16 bytes. At recording to SWF, the number of bits needed for coding the largest value is recorded to the first 5 bit, and then these 4 values in bit representation with a specified bit length. For example, it's necessary to save coordinates (0,0 – 100, 100) or in twips (0,0 – 2000,2000). In bit representation number 2000 = 11111010000 (11 bit + 1 for a sign). We have (5 + 4 * 12) / 8 = 7 byte (almost 2 times less). This approach leads to the fact that some identical tags can have different size. It also applies to Header.

    The second approach is using ZLib compression method both for the whole SWF and for separate tags.

    When a file is compressed, first three parameters of a Header (8 bytes) are not compressed, but the rest are compressed. This explains why it's impossible to read an SWF header only with one read method.