Actimagine Video Codec

From MultimediaWiki
Revision as of 02:30, 3 July 2016 by Kostya (talk | contribs) (Some information about VX)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Codec family created by Actimagine, aimed at use in various CE devices - mobile phones, handheld gadgets, etc. Part of the official Nintendo Gameboy Advance and Nintendo DS SDK.

Videos of this format can be extracted with the ndstool application, a frontend for which is available at http://l33t.spod.org/ratx/DS/dslazy/ , the video files seem to use the extension .vx and starts with a signature of VXDS in the first 4 bytes.

File format

Some of the information here was taken from https://github.com/xoreos/xoreos/blob/master/src/video/actimagine.cpp

Header (all 32-bit little endian words):

 * magic "VXDS"
 * number of frames?
 * width
 * height
 * unknown
 * frame rate
 * audio sample rate
 * audio present flag?
 * max video frame size?
 * audio data offset?
 * file size minus 8
 * always 1?

Then video frames start, then optional audio stream and there are always bytes 00 00 00 00 30 00 00 00 at the end.

Frames start with 32-bit little-endian size minus two.

Video codec description =

This codec is based on ITU H.264 and uses Elias Gamma' codes in most places. Data is coded in 16x16 macroblocks. Each macroblock starts with gamma' code telling its coding mode:

  0 - partition into 8x16 subblocks
  1 - copy 16x16 block
  2 - partition into 16x8 subblocks
  3 - delta 16x16 with MV
  4 - copy 16x16 block with MV from reference 1
  5 - copy 16x16 block with MV from reference 2
  6 - copy 16x16 block with MV from reference 3
  7 - delta 16x16
  8 - partition into 8x16 subblocks, add residue afterwards
  9 - copy 16x16 block from reference 2
 10 - delta 16x16 with MV, add residue afterwards
 11 - add full-block intra prediction
 12 - copy 16x16 block from reference 1, add residue afterwards
 13 - partition into 16x8 subblocks, add residue afterwards
 14 - copy 16x16 block from reference 3
 15 - intra prediction in 4x4 subblocks
 16 - copy 16x16 block with MV from reference 1, add residue afterwards
 17 - copy 16x16 block with MV from reference 2, add residue afterwards
 18 - copy 16x16 block with MV from reference 3, add residue afterwards
 19 - intra prediction in 4x4 subblocks, add residue afterwards
 20 - copy 16x16 block from reference 2, add residue afterwards
 21 - copy 16x16 block from reference 3, add residue afterwards
 22 - add full-block intra prediction and then residue
 23 - delta 16x16, add residue afterwards

"with MV" means that first you read two signed gamma' codes for motion vector delta.

"delta 16x16" means that data is copied with an offset added to each component value (i.e. you read three signed gamma' values, copy block from elsewhere and add delta value to each copied pixel).

Full-block intra prediction reads two methods (for luma and chroma), luma prediction methods are top, left, DC and plane?; chroma prediction methods are DC, left, top and plane?

4x4 block intra prediction seem to predict first luma mode from neighbours, the following ones use 3-bit field (plus a bit read to skip the actual prediction in each case) and has 9 methods now (top, left, DC, various angles), chroma is the same as in the previous case.

Residue is coded as groups of 8x8 semi-macroblocks made of 4x4 blocks. First there's CBP remapped from the gamma' code, top bit is for chroma blocks. Then there are coefficients for 4x4 blocks.

CBP table:

 0x00, 0x08, 0x04, 0x02, 0x01, 0x1F, 0x0F, 0x0A,
 0x05, 0x0C, 0x03, 0x10, 0x0E, 0x0D, 0x0B, 0x07,
 0x09, 0x06, 0x1E, 0x1B, 0x1A, 0x1D, 0x17, 0x15,
 0x18, 0x12, 0x11, 0x1C, 0x14, 0x13, 0x16, 0x19

Coefficients are coded in 4x4 block. First there's a context-dependent static Huffman codebook for coding mode that tells how many non-zero coefficients are there and how many of them form a tail of plus-minus ones. Then there's a context dependent code for telling how many zeroes are at the end of the block. For the tail of ones only signs are coded, the rest of coefficients are coded as (gamma() << level) | get_bits(level) and then a sign where level is initially zero and is increased by one when the absolute coefficient value is greater than the limit for this level. Between coefficients there's a zero-run coded with context dependent code.

Level limits:

 2, 5, 11, 23, 47, 32768

Audio codec description

Audio seems to be some flavour of ADPCM.