Origin Xan Codec: Difference between revisions

From MultimediaWiki
Jump to navigation Jump to search
(Mike, will you ever complete this?)
Line 22: Line 22:
   bytes 12-? - luma Huffman-coded data for frame type 0
   bytes 12-? - luma Huffman-coded data for frame type 0
   or
   or
   bytes 12-15 - offset to some chroma differences?
   bytes 12-15 - offset to chroma differences
   bytes 16-? - luma Huffman-coded data for frame type 1
   bytes 16-? - luma Huffman-coded data for frame type 1


Line 30: Line 30:
   bytes 4-? - possible chroma values
   bytes 4-? - possible chroma values


=== Luma reconstruction for frame type 0 ===
Luma data is packed with left-to-right Huffman codes, chroma data is packed with the same <code>wc3_unpack</code>.
 
=== Intra frame (type 0) ===
 
==== Luma reconstruction  ====


Reconstruction of the first line:
Reconstruction of the first line:
Line 78: Line 82:
         }
         }
         *out++ = byte_l;
         *out++ = byte_l;
    }
==== Chroma reconstruction ====
    while (bytes_decoded--) {
        current_values = LE_16(&mem34) * 2;
        if (current_values != 0) {
            byte_l = (current_values & 0xFF);
            byte_l += mem2C[0];
            byte_l &= 0x3F;
            mem2C[0] = byte_l;
            byte_l = ((current_values >> 8) & 0xFF);
            byte_l += mem2C[2];
            byte_l &= 0x3F;
            mem2C[2] = byte_l;
        }
        mem34 += 2;
        mem2C += 4;
    }
=== Inter frame (type 1) ===
==== Luma reconstruction ====
    while (height_counter--) {
        byte_l = *mem34++;
        byte_l *= 2;
        byte_l += *mem2C;
        byte_l &= 0x3F;
        *mem2C++ = byte_l;
        width_counter = (s->avctx->width - 1) / 2;
        while (width_counter--) {
            byte_h = *mem34++;
            byte_h *= 2;
            byte_h = mem2C[1];
            byte_h &= 0x3F;
            mem2C[1] = byte_h;
            byte_l /= 2;
            mem2C[0] = byte_l;
            mem2C += 2;
            byte_l = byte_h;
        }
        *mem2C++ = byte_l;
    }
==== Chroma reconstruction ====
There are two possible modes - in one mode single chroma differences buffer is unpacked, in another mode two buffers are unpacked and their contents are added together before using in unpacking.
    while (input_size > 0) {
        *mem2C++ = (((*mem34++) << 1) + *mem2C) & 0x3F;
        mem2C++;
        input_size--;
     }
     }



Revision as of 23:38, 8 December 2009

The Xan codec is a codec used in various multimedia-heavy titles from early in the FMV-era of PC computer games. The video was packaged in AVI files along with a custom DPCM audio codec.

While not all of the details have been reverse engineered, the Xan codec is known to use the same byte unpacking algorithm as used in the custom video codec developed for Wing Commander III. Further, it uses Huffman coding and bit packing, though using a slightly different algorithm than its predecessor codec, and it appears to have been designed to easily accommodate a number of video output and scaling modes.

Trivia: All Xan-encoded AVI files contain very interesting comment string inside. 'Xxan video stream, Blue Mu Productions.' What could possible that Blue Mu be? A subdivision of Origin or real codec authors?

Format

This codec is similar to Wing Commander III MVE Video Codec and employs the same packing algorithm. The main difference is that this codec stores information in YUV colorspace (6 bits for Y component, 5 bits for U and V components).

Frame format:

 header:
  bytes  0-3  - frame type
  bytes  4-7  - offset to chroma data
  bytes  8-11 - offset to some luma differences?
  bytes 12-? - luma Huffman-coded data for frame type 0
 or
  bytes 12-15 - offset to chroma differences
  bytes 16-? - luma Huffman-coded data for frame type 1
 chroma data:
  bytes 0-1 - chroma data is YUV420 or YUV410
  bytes 2-3 - offset to Huffman-coded chroma indexes
  bytes 4-? - possible chroma values

Luma data is packed with left-to-right Huffman codes, chroma data is packed with the same wc3_unpack.

Intra frame (type 0)

Luma reconstruction

Reconstruction of the first line:

   byte_l = *unpacked++;
   byte_h = byte_l;
   byte_l *= 2;
   *out++ = byte_l;
   width_counter = (width - 2) / 2;
   
   while (width_counter--) {
       byte_l = byte_h;
       byte_h += *unpacked++;
       byte_h &= 0x1F;
       byte_l += byte_h;
       *out++ = byte_l;
       byte_l = byte_h;
       byte_l *= 2;
       *out++ = byte_l;
   }
   *out++ = byte_l;

Reconstruction of the rest of the lines:

   while (height_counter--) {
       byte_l = out[-width];
       byte_l /= 2;
       byte_l += *unpacked++;
       byte_l &= 0x1F;
       byte_h = byte_l;
       byte_h *= 2;
       *out++ = byte_h;
       byte_h = byte_l;
       mod_width = (-width + 2) >> 1;
      
       while (mod_width < 0) {
           byte_l = out[-width + 1];
           byte_l /= 2;
           byte_l += *unpacked++;
           byte_l &= 0x1F;
           byte_h += byte_l;
           *out++ = byte_h;
           byte_h = byte_l;
           byte_l *= 2;
           *out++ = byte_l;
           mod_width++;
       }
       *out++ = byte_l;
   }

Chroma reconstruction

   while (bytes_decoded--) {
       current_values = LE_16(&mem34) * 2;
       if (current_values != 0) {
           byte_l = (current_values & 0xFF);
           byte_l += mem2C[0];
           byte_l &= 0x3F;
           mem2C[0] = byte_l;
           byte_l = ((current_values >> 8) & 0xFF);
           byte_l += mem2C[2];
           byte_l &= 0x3F;
           mem2C[2] = byte_l;
       }
       mem34 += 2;
       mem2C += 4;
   }

Inter frame (type 1)

Luma reconstruction

   while (height_counter--) {
       byte_l = *mem34++;
       byte_l *= 2;
       byte_l += *mem2C;
       byte_l &= 0x3F;
       *mem2C++ = byte_l;
       width_counter = (s->avctx->width - 1) / 2;
       while (width_counter--) {
           byte_h = *mem34++;
           byte_h *= 2;
           byte_h = mem2C[1];
           byte_h &= 0x3F;
           mem2C[1] = byte_h;
           byte_l /= 2;
           mem2C[0] = byte_l;
           mem2C += 2;
           byte_l = byte_h;
       }
       *mem2C++ = byte_l;
   }

Chroma reconstruction

There are two possible modes - in one mode single chroma differences buffer is unpacked, in another mode two buffers are unpacked and their contents are added together before using in unpacking.

   while (input_size > 0) {
       *mem2C++ = (((*mem34++) << 1) + *mem2C) & 0x3F;
       mem2C++;
       input_size--;
   }

Games Using Xan Video