So, while I still have no idea how this codecs functions I can describe some technical details from it.
First, codec data consists of chunks with tag like 0xA00001xx
and chunk size in the beginning. Some chunks are unique, some may repeat, some are alternative to each other (e.g. there are four different chunk IDs for Huffman tree description, two of them differ only in header before tree data).
Second, some smaller chunks (like 0x09
with 3-byte payload containing some decoding parameters) are obfuscated by XORing with the key derived from main chunk data. Annoying and not adding much protection really.
Third, unlike plain TrueMotion 2, TrueMotion 2X11R6 has 8×8 blocks (and not 4×4), only 3 block types (instead of 7) and single Huffman tree descriptor (instead of one per non-null block types plus one for block types itself). And it’s in a rather curious format too.
Typical TM2X (or TM2A) frame usually (i.e. for both known samples) consists of 0x06
chunk with compressed block data, some small chunks like 0x15
, 0x09
, two 0x02
chunks, about a dozen of 0x0B
chunks and 0x0A
chunk with Huffman code description.
Motion vector coding is represented in several variations: simple signed 8-bit values, MV vector of fixed bit size with bias (both are coded before MV data), some recursive MV coding for large frame areas and even the coding using Huffman coding.
And finally some notes about Huffman coding itself. I’ve not understood it properly yet but here are some notes:
- Huffman code descriptor is actually a 2D table of 8×256 size (it’s stored in compact way in the corresponding chunk), i.e. every byte has a list of up to 8 elements corresponding to it;
- decoding is performed by moving on the 8-element list unless an escape value is seen, then a byte is read from the input and new 8-element list is selected, and after decoding the current position is saved for later (e.g. first you read byte like
0x2A
and it corresponds to a list0, 1, 2, 0x83
— that means on subsequent decoding calls you should get 0, 1, 2, 3 and move to reading a new byte from input). Disclaimer: at least that’s how I understood it, it seems to be a reverse coding to me, i.e. assigning a variable amount of tokens to single byte of input instead of conventional assigning a variable amount of bits to the single token; - in some cases an additional value may be read using both the descriptor and some additional table (it’s added to the result in those cases).