Bink Video: Difference between revisions

From MultimediaWiki
Jump to navigation Jump to search
Line 20: Line 20:
* 4 bits - huffman tree type.
* 4 bits - huffman tree type.


first table seems to correspond to raw nibble coding, so the rest of data exists only for types 1-15
First tree is actually raw nibbles, so no additional data for it.
For other trees leaves symbols should be coded.


* 1 bit - tree type: 1 - small tree, 0 - big tree
* 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.


For small tree:
  Example:
* 3 bits - number of leaves in tree
  read  {5} [1] (3) <9> <1> <7>
* <code>[number of leaves in tree]</code> x 4 bits - leaves code length?
  tree type: 5
  symbols order:  9  1  7  0  2  3  4 5  6  8  A  B  C  D  E  F


Big trees are seemed to be generated first by making pairs (i ; i+1) or (i+1; i) depending on bit read and then sorted by using several passes of merge sort; this merge sort also uses bits instead of comparisons to sort that list in some order.
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.


== Decoding ==
== Decoding ==

Revision as of 01:22, 28 June 2009

  • 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.

Decoding

Block types

NOTE: This section is incomplete

0

Copy 8x8 block from previous frame to current frame

1

Read secondary block code

(TODO)

1 - 3

Fill 16x16 block with coded byte

6

Fill 8x8 block with coded byte