Electronic Arts CMV
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.
See Electronic Arts Formats for file format description.
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
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
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 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
This chunk signals the end of the video stream. It contains no payload data.