Description of the Apple Video (rpza) Codec by Roberto Togni (rtogni at bresciaonline dot it) v1.1: March 24, 2003 ======================================================================= NOTE: The information in this document is now maintained in Wiki format at: http://wiki.multimedia.cx/index.php?title=Apple_RPZA ======================================================================= Copyright (c) 2002-2003 Roberto Togni Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". Introduction ============ The Apple Video codec (fourcc rpza and azpr) is used to compress frames in Apple Quicktime files. It's a computationally simple codec that operates on 4x4 pixel blocks using 15-bit RGB color values. Each chunk of data encodes a single frame. No data is shared between chunks. Basics of rpza Data and Decoding ================================ All multi-byte values are stored in big-endian format. An rpza decoder renders 4x4 pixel blocks from left to right, top to bottom. The source data are 15-bit RGB values, stored as 16-bit words. MSbit of color values is used as a flag or ignored. The first byte of a chunk is probably a flags byte. XAnim's comments seem to imply that this byte is always 0xe1. No other value observed in this byte. The meaning of the byte is unknown. Bytes 2-4 are the length of the chunk. This value should match the value transported in the Quicktime file's video chunk length atom. After the first 4 bytes, an rpza chunk is a stream of opcodes and associated data. The length of data varies with the opcode. The opcode is encoded into the next byte in the stream. The meaning of each opcode is detailed next. Chunk structure --------------- +--------+-----------+--------+---------+------//--+--------+---------+ | 1 byte | 3 bytes | 1 byte | # bytes | ... | 1 byte | # bytes | +--------+-----------+--------+---------+------//--+--------+---------+ | 0xe1 | chunk_len | opcode | data | ... | opcode | data | +--------+-----------+--------+---------+------//--+--------+---------+ Note: opcode: only some bits of this field contain the opcode, the others are part of data field # : data length, depends on opcode. Can be 0. Opcodes ------- Standard rpza opcodes are stored in upper 3-bit section of opcode byte. There is also a special opcode, where the upper bit (bit 7) is 0. Standard Opcodes ================ A standard opcode is made by an opcode value and a block counter. A single opcode can affect up to 32 4x4 blocks. Standard opcode structure: +-------+-------+ | 3 bit | 5 bit | +-------+-------+ | opc | blk | +-------+-------+ opc: opcode value blk: block counter -1 (add 1 to blk to get block counter) 0x80: Skip blocks ----------------- This opcode instruct the decoder to skip blocks in the output frame. If there are 4x4 pixel blocks in the previous frame that are the same as in the current frame, there's no point in rendering them again, so these opcodes allow the decoder to skip blocks. No data field is used by this opcode. 0xa0: Single color ------------------ This opcode instruct the decoder to paint the next n blocks the same color. The color to paint the block is encoded into data field. Data field is 2 bytes long. 0xc0: 4 colors with index ------------------------- This opcode specify a quad of colors with which to paint the next n blocks. Two colors are stored in data stream, the others are computed by the decoder. Data field is (4 + n*4) bytes long. The decoder computes 4 color as follows: Get two color from data stream and call them colorA and colorB. Build the other two color using the following formula, applying it to each color component color0 = colorB color1 = (11 * colorA + 21 * colorB) / 32 color2 = (21 * colorA + 11 * colorB) / 32 color3 = colorA As an example, red component of color 1 is (11*Red_colorA+21*Red_colorB) >> 5 For each block to be rendered, there are 4 bytes (called a, b, c and d in this example) in the stream that are arrays of flags which specify which of the 4 colors in the selected pair will paint which pixels in the block. The flags are arranged as follows: a76 a54 a32 a10 b76 b54 b32 b10 c76 c54 c32 c10 d76 d54 d32 d10 For example, if the lower 2 bits of byte a are 11 (3 decimal), then color 3 of the selected color quad is placed in the upper right corner of the block. Special opcode ============== A special opcode have the MSbit of opcode byte equal to 0. Decoder needs to check following bytes in the stream to decide what to do with the data. This class of opcodes affects only one 4x4 block. This opcode is also the MSB of two-byte value colorA, the LSB is the next byte from data stream. The MSbit of next byte tell the decoder what to do: MSbit is 1: This opcode is the same as 0xc0 (4 colors with index), using colorA computed above and entering opcode 0xc0 algorithm where it looks for colorB into the stream. Data field is (1+2+4) bytes long. MSbit is 0: This opcode fills the next block with 16 different colors. The first color is colorA computed above, the next 15 colors come from data stream. Data field is (1+15*2) bytes long. Final notes =========== There is an unused value in standard opcode encoding space, 0xe0. I'm not sure if a chunk have to encode all blocks or it can skip last blocks if there is no need to encode them in current frame. References ========== XAnim http://xanim.polter.net/ ChangeLog ========= v1.1: March 24, 2003 - licensed under GNU Free Documentation License v1.0: February 10, 2002 - initial release GNU Free Documentation License ============================== see http://www.gnu.org/licenses/fdl.html EOF