Bink Video
- FourCC: BINK (note that some FourCC lists assert that BINK is a FourCC for general-purpose multimedia containers; however, Bink data is always known to be encapsulated in a custom container format)
- Company: RAD Game Tools
- Samples: http://samples.mplayerhq.hu/game-formats/bink/, countless video games
Bink is a video codec that purports to use every video coding technique (DCT, FFT, Wavelet Coding, Vector Quantization, Motion Compensation) under the sun and used in a large number of computer and console games. The video is packaged in custom Bink files.
Each plane is coded separately. The Y plane is always coded first in each frame.
Format
Bitstream is read LSB from 32-bit little-endian words.
Frame is coded as three planes.
Each plane starts with Huffman codebooks: two 4-bit ones, one 8-bit (which really consists of seventeen (16 plus one special) 4-bit codebooks) and four 4-bit ones.
Huffman trees
There are 16 predefined Huffman trees, Bink frame only stores tree number and sophisticated coding of leaves values.
- 4 bits - huffman tree type.
First tree is actually raw nibbles, so no additional data for it. For other trees leaves symbols should be coded.
- 1 bits - symbols are coded explicitly (by selection)
If that flag is one, read 3 additional bits which determine number of symbols out of order, then read those symbols (4 bits per each symbol), the rest of symbols should go in normal order.
Example: read {5} [1] (3) <9> <1> <7> tree type: 5 symbols order: 9 1 7 0 2 3 4 5 6 8 A B C D E F
In other case symbols are coded by shuffling:
- 2 bits - shuffle depth
First divide all symbols into pairs and read 1 bit for each pair to decide whether swap this pair or not.
Example: original data: (0 1) (2 3) (4 5) (6 7) ... read bits: 0 1 1 0 ... output: (0 1) (3 2) (5 4) (6 7) ...
if shuffle depth is zero, end operation; otherwise perform merging.
void merge(uint8_t *dst, uint8_t *src1, uint8_t *src2, int size) { int size1 = size, size2 = size; do{ if(getbit()){ *dst++ = *src2++; size2--; }else{ *dst++ = *src1++; size1--; } }while(size1 && size2); while(size1--) *dst++ = *src1++; while(size2--) *dst++ = *src2++; }
If depth is one, divide symbols into pairs and merge neighbouring pairs (i.e. [0 1] and [2 3], [4 5] and [6 7], etc.) If depth is two, divide result into quartets and merge quartet 0 with quartet 1 and quartet 2 with quartet 3. For depth = 3 additionally divide result into two halves and merge them too.
Or, more clearly:
depth = getbits(2); for (i = 0; i <= depth; i++) { int size = 1 << i; int skip = size * 2; for (j = 0; j < 16; j += skip) merge(tmp + j, symbols + j, symbols + j + size, size); memcpy(symbols, tmp, 16); }
Bundle reading
8-bit values are decoded with bundles. Bundle consists of 17 Huffman trees - one to decode upper 4 bits and 16 trees that are used to decode lower 4 bits. Those lower 4 bits are used as tree number to decode next low nibble.
Decoding
Frame
for each block a lot of values should be decoded (value may be taken from cache if previous decode returned run of values):
- block type - 4 bit RLE bundle
- sub block type - 4 bit RLE bundle
- colors data (for filling blocks) - 8 bit bundle
- pattern - 8 bit pair bundle
- x motion offset - 4 bit signed bundle
- y motion offset - 4 bit signed bundle
- DC for interblock? - 16 bit delta
- DC for intrablock? - 16 bit delta
- pattern colors run length - 4 bit bundle
Block types
NOTE: This section is incomplete
0
Copy 8x8 block from previous frame to current frame
1
This is 16x16 block which has its own subtype, which corresponds to other block types (range 3-9). Blocks should be decoded in the same way and then scaled twice.
2
Copy 8x8 block from previous frame with some offset (x and y values decoded at the beginning of the block)
3
Fill 8x8 block with pattern 4 bits - pattern index
first 63 coefficients in block are decoded in this way:
run = next value from Pattern Colors Run Length; if(getbit()){ memset(block, Colors[0], run); Colors++; }else{ memcpy(block, Colors, run); Colors += run; } block += run;
Last block element is taken from Colors
values
4
looks like block type 7 without DCT, i.e. MC and coded difference only, 7 bits - number of elements coded
5
intrablock with DCT coefficients and 4 bits quantizer
6
Fill 8x8 block with one value from Colors
7
interblock with motion vector (x and y values decoded at the beginning), DCT coefficients and 4 bit quantizer
8
Fill block with two colours taken from Colors
values using 8 values from Patterns
9
Fill 8x8 block with 64 values from Colors</code