I think this should be in every first aid kit.
OMG
March 23rd, 2013On some screen codecs
March 5th, 2013Recently my attention was drawn to two screen codecs. So I’ve looked a bit closer at them (I’m not going to implement them — at least now, simian audio codec is waiting) and here are the most interesting bits to me.
Dxtory codec. I don’t know if it uses prediction or not but the coding is extremely simple: read unary code (1-8 bits), if the code is 8 (escape) then read byte for a new value, otherwise retrieve value from LRU list and of course move/put the new value to the beginning of that list.
The organisation into slices and decoding for different colourspaces is trivial.
Mirillis FIC Video. This one has more complexity: it operates on 8×8 blocks. Block is coded in the following way: if the flag is present then the block is skipped, otherwise read 7 bits for the number of coefficients to decode and the coefficients (signed exp-Golomb coded). Zigzag scan, IDCT, output.
Boring.
A new record
March 4th, 2013I thought that there’s no codec more horrible than Go2Despair and was proved wrong again. Here’s the even worse pair: Dxtory codec and its standalone companion PackBit.
DxtoryCodec.dll is 8.2MB which rivals Go2C++Hell because it’s standalone decoder without any additional code. PackBitCodec.dll is even more elegant. Of the total size of 672256 bytes more than 357000 bytes are occupied by the code of one function (that’s 3-6 times more than the ordinary zlib-based codec complete DLL file). Truly some people should not be allowed to program.
More about Monkey’s Audio filter changes
March 3rd, 2013In the previous post I gave general overview of codec changes, now I’m going to look more deeply at the filter changes with time.
- 3950 — current mode with up to three layers of IIR filters
- 3930 — simpler filters: no third layer (there was no insane compression level back then) and the difference between predicted and actual value was not used.
For the older versions there are differences in the implementations of the filters for the different compression modes.
Fast compression:
- 3200 — order 2 adaptive prediction (i.e. previously decoded and adjustable prediction value are used in prediction)
- 0000 — almost the same but with different rules for adjustment factor updating
Normal compression:
- 3800 — two layers of filters: order 4 adaptive prediction and order 2 afterwards
- 3200 — the same structure, different rules for updating
- 0000 — three layers with orders 3, 2 and 1 and different updating rules
High compression:
- 3700 — first it tries first order adaptive prediction with the delay of 2-16 (i.e. the next to previous element is used for prediction) and normal mode decompression afterwards (different decoding for 3800 of course)
- 3600 — the same but delays are 2-13
- 3200 — the same but delays are 2-7
- 0000 — orders 5 and 4 and different updating rules
Extra high compression:
- 3830 — an IIR filter resembling the one used in the newer Monkey’s Audio versions
- 3800 — some filter parameters were half as much as in 3830 and there was no delay 2-8 filtering
- 3600 — delay filtering plus high filtering (which is delay filtering plus normal filtering, which can be expressed as a layer of filtering over fast filtering)
- 0000 — essentially the same but with different prefiltering
Monkey’s Audio: noted differenced between versions
February 28th, 2013While preparing for working on old APE versions support I finally got courage to try and trace all changes for different versions. So here’s the list of internal versions and the changes they introduced:
- 0000 — the reference version for all prehistoric version. Before version 0000 it was fine, then it all got worse IMO.
- 3320 — changes in the filters
- 3600 — changes in the filters
- 3700 — changes in the filters
- 3800 — blocks per frame changed for extra high compression level; changes in the filters (yawn)
- 3810 — frame start at byte boundaries now
- 3820 — special codes extension (signalled by top bit of CRC set to one)
- 3830 — filter lengths and some implementation details changed
- 3840 — CRC calculation algorithm changed a bit
- 3870 — significant changes in residue coding
- 3890 — small changes in residue coding
- 3900 — residue coding format has changed seriously.
- 3910 — small change in the residue coding (more than 16 bit values can be coded now)
- 3930 — significantly changed format introduced (both filtering and coding scheme were changed)
- 3950 — filter format changed a bit (and insane compression mode is added somewhere after that), blocks per frame is changed too
- 3960 — some small and compatible change in the bitstream (consuming two last bytes or not)
- 3980 — file format is changed a bit; filtering process has changed a bit too.
- 3990 — the latest (known) format. Residue coding has changed.
Do you still wonder why I strongly dislike this format?
Preserving extinct formats
February 27th, 2013By the request of one guy (he has provided samples as well) I shall work on supporting old Monkey’s Audio versions (before 3.95).
Why? Because the latest official version of Monkey’s Audio has dropped support for those files, because I wanted to support such files since really long time (just didn’t have a good opportunity to do that) and because I definitely need a distraction from Go2Insanity codec (I shan’t blog about it anymore).
Well, let’s see what the old versions of the worst (known) designed lossless audio codec have to offer me.
Now (hopefully) the last post about Go2Disassembly details
February 18th, 2013I’ll update codec details on our wiki and hopefully can forget about it. Let somebody French-speaking complete it.
There are many codecs out there to reverse engineer, including worthier ones. On the second thought that would define almost every codec.
Update: filled all information I had, the rest is up to somebody with the debugger and motivation to do it.
Another piece of digital archeology news
February 14th, 2013After investigating the smallest available pile of fossilised dung called Go2Cesspit (only 2.5MB instead of 15MB for the current version) the G2M1 can be reconstructed. It had the same tiled structure as its successors but it coded all tiles with ELS only, no combining with JPEG data.
And the full history of Go2UnwantedPlaces evolution (there definitely was no intelligent design for obvious reasons):
- Citrix licenses image coding from Accusoft (ELS-based), uses it to release G2M1.
- They want to improve compression and try to code some blocks in the different way. JPEG to the rescue! That’s how G2M2 was born (compression method 2).
- G2M3 looks like marketing bump since image coding has not been changed.
- For some reasons they replace ELS part with simple deflated raw bitmap. That’s G2M4 now (and compression method 3).
Further findings may correct this system of course but so far it looks like this.
P.S. If you want to have G2M1 supported then send samples and support requests to VideoLAN. They will be grateful for sure.
Now the final words about Go2UselessTalk
February 13th, 2013Now I can officially say that G2M4 is essentially reverse engineered. It indeed uses zlib-compressed image for sharp details (it’s called “synthetic layer” internally) and JPEG compression for smooth detail (it’s called “natural layer” internally). The only catch — it’s not plain JPEG coding, it codes only some block with JPEG and uses a special way to restore a sparse image.
The idea of this J-BKoding (not the same as J-BKoder in Go2Coven!) is simple: only the blocks referenced from top layer are coded and to save space and improve compression they are coded continuously. So how you know how to restore the picture back? Easy! JPEG data is preceeded by number of macroblocks coded and flags (in bytes, LSB first) telling whether the block is decoded one or skipped. I suspect that something similar might be true for the previous versions of the codec too, because quite often decoded JPEG data showed that its width is less than expected.
Here’s the output of the previous version with synthetic layer only (demonstrated at FOSDEM to the close circle of trolled people):
New version (quick hack):
Now any VideoLAN guy should be able to implement a decoder for it.
A few words about Go2WasteTime version 2/3
February 9th, 2013As some people know, there was Go2UselessActivity decoder for Libav showcased at FOSDEM (on an ARM-based laptop even). It decoded all known variants of the codec with varying degress of success (i.e. output ranged from being completely garbage to being slightly recognizable). Some guy nicknamed “j-b” was really happy for some unknown reason.
Let’s consider a purely theoretical situation that somebody needs Go2EncountersOfTheWorstKind 2/3 and wants to know how it works (usually it’s either one or another or none). As it’s known already it combines ELS-coded images with JPEG-coded data for some pixels that are coded transparent in ELS. JPEG data, to quote j-b
is boring, so let’s look at ELS image coding.
The coder used is the augmented ELS coder by Douglas M. Withers (still available somewhere in Internet insize OSAUGELS.ZIP) with the same tables (36 jots per byte). The only interesting thing is how the image itself is coded with this binary coder.
- Unsigned values are decoded as unary prefix for number of bits to follow and then the actual value, signed values are coded as unsigned with an usual scheme
x -> 2*x, -x -> 2*x - 1
(zero is explicitly signalled by number of bits being zero of course). - Pixels are coded as RGB triplets, using median prediction from top, top left and left neighbours if possible. If prediction is used then pixels are coded as differences to
(G, R-G, B-G)
predicted value. - General image coding is conceptually simple: the image is coded as runs of RGB triplets if possible; in some cases if it’s possible to decode pixel from cache it’s done so. If that’s not possible too then one pixel is coded as described above.
Here’s slightly more detailed image decoding description:
for (y = 0; y < height; y++) {
x = 0;
while (x < width) {
if (x > 1 && y > 0 &&
rgb[x - 1][y] != rgb[x - 2][y] &&
rgb[x - 1][y] != rgb[x ][y - 1] &&
rgb[x - 1][y] != rgb[x - 1][y - 1] &&
rgb[x - 1][y] != rgb[x - 2][y - 1] &&
pixel_in_cache(rgb[x - 1][y]) {
rgb[x][y] = decode_pixel_with_prediction(x, y);
x++;
continue;
}
decode_run(x, y, &run_length, &pix);
if (run_length > 0) {
// pixel value may get changed here
decode_modified_pix(x, y, run_length, &pix);
while (run_length--)
rgb[x++][y] = pix;
} else if (decode_from_cache(&pix)) {
rgb[x][y] = pix;
x++;
} else {
rgb[x][y] = decode_pixel_with_prediction(x, y);
x++;
}
}
}
Hopefully no more information will follow soon.