Electronic Arts CMV

From MultimediaWiki
Jump to: navigation, search

CMV is a video codec used by at least one Electronic Arts video game. It operates in the 8-bit RGB colorspace and uses a 4 x 4 pixel inter-frame block replacement technique.

Chunk Types

See Electronic Arts Formats for file format description.

MVIh ("Header")

The header chunk describes the image dimensions, frame rate and palette. This chunk type can occur multiple times in file to convey changes to the color palette.

Offset   Data_type   Name         Description
0x0000   le_16                    unknown
0x0002   le_16                    unknown
0x0004   le_16       width        image width (pixels)
0x0006   le_16       height       image height (pixels)
0x0008   le_16                    unknown
0x000a   le_16       frame_rate   frame rate (frames per second)
0x000C   le_16       pal_start    palette start index
0x000E   le_16       pal_count    number of palette entries
0x0010   array                    palette entries
For pal_count palette entries
   (u8) red_component
   (u8) blue_component
   (u8) green_component

MVIf ("Frame")

The frame chunk begins with an le_16 indicating the frame type, where zero and one indicate intra and inter frames respectively. Values greater than one are considered to be inter frames by NHL 95 decoder.

Offset   Data_type   Name         Description
0x0000   le_16       frame_type   frame coding type, where 0=intra, 1=inter

Intra Frames

A raster buffer immediately follows the frame_type. Pixel values are arranged in left-right, top-bottom raster order. Each pixel value indicates a color palette index.

For width pixels
For height pixels
   (u8) pixel_value

Inter frames

Inter frames contain two buffers. The first immediately follows the frame_type field, and stores a byte value for each 4 x 4 pixel block present in the image. The length of the first buffer can be calculated as width/4 * height/4 bytes. Each sample file was found to use modulo 4 image dimensions.

The second buffer immediately follows the first and stores additional inter data, spanning the remainder of the chunk payload.

For height / 4
For height / 4
  (U8) motion_value

The decoder iterates through the first buffer, and maintains a pointer to the second buffer from which bytes can be fetched in sequential order.

When motion_value is not equal to 0xFF, pixel values for the current block is copied from a 4 x 4 block from last decoder frame. The source block is offset by a motion vector. The motion vector is calculated from the high and low nibbles of motion_value. Motion vectors are permitted to fall outside the image boundary, in which case pixels that are outside the boundary are considered to equal zero.

mv_x = (motion_value low nibble) – 7
mv_y = (motion_value high nibble) – 7

When motion_value is equal to 0xFF, a "byte" is fetched from the second buffer pointer. If this byte is not equal to 0xFF, then pixel values for the current block is copied a 4 x 4 block from the second-last decoded frame. The motion vector is calculated from the byte value using the method described above.

If the fetched byte is equal to 0xFF, then pixel values for the current block are fetched from the second buffer pointer. Pixels values are arranged in left-right, top-bottom raster order.

For four pixels
For four pixels
   (u) pixel_value

MVIe ("End")

This chunk signals the end of the video stream. It contains no payload data.