Archive for the ‘Game Video’ Category

A bit about old Bink

Sunday, March 7th, 2010

I don’t think you’ll ever encounter Bink video version ‘b’, known samples were dug out from game data of certain New World Computing games. And looks like they are not supported by official software anymore. But why that can stop us from looking at it?

This information is based on findings by certain FFmpeag deaveloper and me looking at disassembly for similarities with newer Bink version.

The main difference is that this version does not employ Huffman coding at all. All bundle data is stored in raw form, 4-11 bits per entry depending on bundle type. Number of elements in bundle is stored as 13-bit number, newer version uses different number of bits depending on plane width.

Also this Bink used floating-point version of DCT (but constants are the same as in integer version employed by latter codec version).

Coding methods (block types) are in totally different order as well. And 8×8 -> 16×16 scaling block type was not devised in that time either. Bundles contain slightly different data as well — for example, quantisers and number of residue masks are there but pattern run block uses diminishing number of bits to code runs instead of reading it from bundle (indeed, if you have to decode 48 more block elements you need to read 6 bits but when there are mere 7 block elements left 3 bits are enough).

I’ve not looked too close at DCT coefficient/residue coding methods but they seem to resemble those used in newer version of codec.

Short conclusion: while Bink video codec steadily improved, most concepts are remained the same (but there’s a bigger leap between versions ‘b’ and ‘f’ than between ‘f’ and ‘i’, the latter are almost backwards compatible). And maybe we’ll see decoder for it in FFmpeg for completeness sake.

Pending work for FFmpeg

Saturday, December 19th, 2009

Here are some pictures decoded with game decoders I’ve more or less finished in my free time:

While logotype in the middle should be recognisable to almost everybody (it’s from video file embedded in another player/converter for that format), others are not so famous.
Yes, colour planes are swapped but that’s not critical.

Left picture is taken from Wing Commander IV trailer packed with Xan codec. It has a very long history — it was 90% complete even before I joined FFmpeg project. The only caveat was that it outputs YUV format while Mike thought it was 16-bit RGB. Also nobody was interested in completing it (including Mike and me). Well, it’s almost there.

Right picture is from Descent III intro encoded with Interplay Video 16-bit version. I’ve looked at it once, almost got it right. Main thing I missed is that is stores motion vector data at certain offset, not along with other data as it did in 8-bit version. Now it plays fine though.

Another funny thing I remember is that there were complaints on detection of 16-bit variant. And what do you know? That information was available for ages at container description page. Sometimes it’s useful also to read Multimedia Wiki, not only write to it.


What next? I don’t know, there so many things to do — finish Flash Video 2 decoder, integrate Auravision 1/2 decoder before it rots, have another stab at some formats like Apple Intermediate codec or some codecs from Windows Media family.

At least I know that FFmpeg may be a bit closer to its one of unofficial ultimate goals — converting everything.

Bink: pattern-run blocks

Friday, September 4th, 2009

And now for something completely the same.

Let’s talk about most interesting block type in Bink. I don’t know official name for it but I call it pattern-run block because of the way it’s coded. Idea is simple: there are runs of single colour and blocks of different colours like in your ordinary RLE; what can be interesting in that? But there is one thing — block is filled with runs/copies not in usual scan orders but following one of 16 predefined patterns – columns, spirals, Hilbert curve (Zelda pattern for some of us), whatever.

Here’s an example:
Scan pattern #13
(and SVG version)

I think it’s obvious how this helps block compression. The only bad thing about it is the fact it did not appear in Smacker (mostly because Smacker uses 4×4 blocks).


This concludes my series of posts about Bink.
“Works for me” patch against FFmpeg r19754 is located here.

Bink: a bunch of peculiarities

Thursday, September 3rd, 2009

I’ve mentioned before that Bink differs greatly from other codecs. Now I want to walk over general structure of it and mark all peculiarities I’ve seen so far.

  1. Huffman coding. I think I’ve mentioned it enough times.
  2. Data coding. The fact that different values (block types, colours, run values) are coded in so-called bundles (i.e. groups) for at least one row of blocks at once. So when starting decoding new row bundles are checked whether there’s enough data and more is decoded if needed.
  3. 16×16 and 8×8 block mix. Sometimes encoder inserts 16×16 block into usual array of 8×8 blocks. Looks like those blocks can happen only on even positions which eases skipping decoded part of it. 16×16 block contents are actually 8×8 block contents scaled twice.
  4. Coding modes. There are 10 block types; three of them belongs to vector quantisation techniques (I’ll write another post about special run-length pattern block), two block types use DCT (more below) and another block type uses special coding for residue without any additional transform.
  5. DCT coefficients coding. I’ve written a bit about it already. Have I mentioned they also use non-standard scan order (designed for pairs of coefficients)?
  6. Coefficients quantising. There are 16 possible quantisers – 1, 1 1/3, 1 2/3, 2, 2 2/3, 3 1/2, 4, 5, 6, 8, 12, 17, 22, 28, 34 and 44.

I suspect that some of the things are legacy of Smacker and really clean design would go in slightly other direction – it’s not pure vector quantisation as it was but it’s not pure DCT-based codec either.

As for the progress: I have more or less working decoder in my own build of FFmpeg. When somebody kicks certain devs to push Bink demuxer and audio decoder into SVN codebase, I’ll give my decoder with that. Until then just wait.

Bink: ‘lossless’ block coding

Wednesday, September 2nd, 2009

First of all, I’d like to note that those names are taken from Bink code. In reality ‘lossy’ block is used as is and ‘lossless’ block is DCT coefficients.

And now, the differences:

  • in ‘lossless’ mode coefficients are decoded until mask becomes zero, there’s no explicit number of coefficients
  • coefficient bits are stored explicitly, not as several masks: coef[x] = mask | get_bits(log2(mask));
  • starting list somewhat differs

For those who for some unknown reason are interested in RE progress, I can say that my implementation is still far away from perfect. It crashes on 640×480 BIKi files and for those two files it plays (BIKf and BIKi) it gives barely recognisable image — I blame DCT and dequantisation (I haven’t looked at them yet).

Bink: ‘lossy’ coefficients reading.

Saturday, August 29th, 2009

RTMP client seems to work fine, RTMP support in FFserver is not that close, so I work on REing some codec which seems to be rather widespread in games.

OK, now to technical details. ‘Lossless’ coefficient coding is similar but a bit more complicated.

For each 8×8 block there is 7-bit number specifying number of masks to read (mask = part of the coefficient), slightly resembling progressive JPEG coding; coefficient value may be composed from several masks, high bits are decoded first. Decoding continues until all masks are read.

Coding method is not that comprehensible though: there is list of start coefficient and modes, so decoding iterates over this list and performs some action depending on mode. Have I mentioned that aforementioned list may change during operation?

And here’s decoding algorithm (if I got it right):


mask = 1 < < get_bits(3) iterate over already decoded coefficients, if read bit = 1 then add mask to the coefficient iterate over list of modes until end is reached, if (coef,mode)==(0,0) or read bit = 0 then skip current entry:   mode = 0:    set current entry to (cur_coef+4; mode = 1)    for(i=0;i<4;i++, cur_coef++){     if(get_bit()) prepend list with (cur_coef, mode = 3)     else coeffs[cur_coef] = get_bit() ? -mask : mask;    }   mode = 1:    set current entry to (cur_coef; mode = 2)    append (cur_coef+4; mode = 2), (cur_coef+8; mode = 2), (cur_coef+12; mode = 2) to the list   mode = 2:    set current entry to (0; mode = 0)    for(i=0;i<4;i++, cur_coef++){     if(get_bit()) prepend list with (cur_coef, mode = 3)     else coeffs[cur_coef] = get_bit() ? -mask : mask;    }   mode = 3:    coeffs[cur_coef] = get_bit() ? -mask : mask;

Brief notes about Bink

Monday, July 13th, 2009

If you play a lot of games (or maybe not that much) andd are interested in watching their FMVs you should hear about Bink sooner or later.

This is rather widespread codec in games and it’s sad we still don’t have an opensource decoder for it.

Here are some facts about it:

  • Container format seems to inherit a lot from Smacker.
  • There are two different audio codecs differing by transform.
  • Bink video is mostly static Huffman coding + vector quantisation or DCT

So, why not reimplement it?
Here are some more details about video:

  1. It employs static Huffman coding – there are 16 predefined trees which are used to decode a lot of data — the only exceptions are block coefficients. Tree definitions include only tree number and how to reorder table of symbols for current data.
  2. Almost all values are coded in bundles for several blocks at once (usually for half of a frame)
  3. 8-bit values may be encoded as independent nibbles or high nibble may have context-dependent encoding when it’s encoded with a tree number equal to the last high nibble (so you need 16+1 trees for that but who cares).

The rest will be available as it goes.

A bit on Interplay MVE 16-bit

Wednesday, April 29th, 2009

For those, who are interested in playing 16-bit MVE files (yes, Mike, I am talking about you) here are some bits of information I’ve gathered at my leisure:

  • you have to skip 16 bytes from block map at the beginning instead of 14 for 8-bit MVE
  • colours are now stored as 15-bit (obvious, isn’t it), and high bit may be set for pattern fill order (8-bit MVE just compared colour values, which still works)
  • for some opcodes pattern fill order was changed a bit (i.e. subblocks scan order)
  • some opcodes meaning was changed completely. Opcode 3 does not requires additional bytes to be read anymore.

I didn’t have a desire to complete it, especially because it’s no fun to debug how motion is stored, so I just hacked existing decoder a bit to decode 16-bit files. Here’s a picture produced by maimed libavcodec/ipvideo.c:

interplay16

The list of game codecs I want to have in FFmpeg

Tuesday, December 2nd, 2008

One of FFmpeg advantages is that it supports decoding of many fringe formats, especially game formats. My favourite is Sierra VMD but there are several other formats I’d like to be able to play:

  • LucasArts SMUSH (there was a patch for playing some variants, the rest could be made from ScummVM code)
  • Discworld II and III video format (if only ScummVM developers got the code for DW2 at least)
  • Indeo 4 and 5
  • Bink (if only certain person worked on REing it instead of formats used in EA games)

Code donations are welcomed 😉

Update: ScummVM has DW2 BMV decoder now.

A RE Puzzle

Sunday, September 21st, 2008

There is a codec, little is know about it.

Here are some of its features:

  • it codes frame as a three planes
  • it employs motion compensation
  • it employs old-school vector quantization — fill block, fill block with mask, …
  • each value in the stream is coded as the run of values plus actual value coded as several Huffman-coded nibbles (yes, each 4 bits are coded with own Huffman tree) plus sign bit if applicable
  • sometimes it performs DCT to restore block content

Try to guess what’s its name.

Hint: MultimediaWiki contains a description of the codec with the similar bitstream reading techniques, which is a relative of this codec.

And, no, since I’m engaged in AAC encoder, I won’t RE nor write decoder for it (at least in the near future).