4

I am trying to write a decoder for an old video format used in a DOS game, the Psygnosis SMV video format, but I'm having a hard time understanding the image decoding process, specifically this section:

Macroblocks drawing

Macroblocks are stored in the following format:

 u8 pixels[16 * num_mblocks]
 u4 nibbles[num_mblocks]

Size of pixels[] is equal to ST chunk's nibbles.
For each macroblock draw it by indexing its pixels by nibbles.
First nibble stored in top 4 bits of byte.

Here are the properties of the frame I am trying to decode:

  • image width = 320
  • image height = 192
  • macroblock width = 16
  • macroblock height = 16
  • nibbles = 3840
  • frame size in bytes = 34560

So according these, I computed the following values:

num_mblocks = nibbles / 16 = 3840 / 16 = 240 macroblocks

further checking:
(image width / macroblock width) * (image height / macroblock height)
= (320 / 16) * (192 / 16)
= 20 * 12
= 240 macroblocks

1st problem:

The size of u8 pixels[16 * num_mblocks] is indeed 3840 bytes, but what is the size of u4 nibbles[num_mblocks] supposed to be ? 240 bytes or half that amount since the type is u4 ?

2nd problem:

When I divide the frame size in bytes by the number of macroblocks I end up with only 144 bytes per macroblock (34560 / 240 = 144), but to me this is very far from what it's supposed to be, I guess I'm wrong somewhere.

3rd problem:

The author wrote:

For each macroblock draw it by indexing its pixels by nibbles.

But what does that mean exactly ?

Question

Can you explain/shed some light on how one is supposed to decode a frame ?

3

NB: This is an assumption which may or may not be true; I haven't tested that against any real file.

It seems like the creators of the file format have been trying to save some space. They want to encode 256 colors ("to encode 8-bit palettized video"), so they'd need one byte per pixel. However, a certain smaller area of the screen ise likely to contain the same color pixels repeatedly. So, I'd say that each macroblock can contain only 16 different colors, representable in 4 bits/one nibble.

From u8 pixels[16 * num_mblocks] it seems like each macroblock has 16 pixel definitions, which are indexes into the general palette table, and need 1 byte each. What follows is one nibble per pixel which is an index into pixels.

So, for example, the pixels for one macro block would have 16 bytes which are indexes into the palette; which may look like this: (Sorry for some of the color names; i ran out of names that fit in 5 characters ...)

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
+  1  +  2  +  3  +  4  +  5  +  6  +  7  +  8  +  9  +  A  +  B  +  C  +  D  +  E  +  F  +
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
| red |green|blue |yellw|magnt|cyan |grey |black|orang|gold |aqua |azure|ivory|plum |wheat|
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----

Next, you need one nibble per pixel which is an index into that table. So the bytes CA 53 2D would represent 6 pixels being azure, gold, magenta, blue, green, and ivory.

So for a macroblock of 256 pixels you need 16 bytes for the pixel table, and 256/2=128 bytes for the pixels. Which sums up to the 144 that you calculated. The u4 nibbles[num_mblocks] is probably wrong and should be u4 nibbles[num_mblocks*pixels_per_mblock]

  • Thank you, I've been digging using your answer, however, I have an incorrect picture ... I started to suspect my implementation of that LZ77-like decompression and decided to attack the simplest thing in the format : decompress packed music chunks; while the algo produces the exact number of bytes, the content is wrong ... I'm actually struggling with this part ! – Aybe Nov 16 '16 at 21:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.