Karl Morton's Video Codec: Difference between revisions

From MultimediaWiki
Jump to navigation Jump to search
(Preliminary format description)
 
(4 intermediate revisions by 3 users not shown)
Line 1: Line 1:
* FourCC: KMVC
* FourCC: KMVC
* Samples: [http://www.mplayerhq.hu/MPlayer/samples/V-codecs/KMVC/ http://www.mplayerhq.hu/MPlayer/samples/V-codecs/KMVC/]
* Samples: [http://samples.mplayerhq.hu/V-codecs/KMVC/ http://samples.mplayerhq.hu/V-codecs/KMVC/]


KMVC is used on various ''Worms'' PC games.
KMVC is used on various ''Worms'' PC games.


== Common details ==
== Common details ==
This codec operates on 8x8 or 16x16 blocks in 256 colors mode. This codec is also employs exotic bitstream reading: actually you need to read byte and when it's exhausted, read another byte, so flags and other data are very mixed.
This codec operates on 8x8 or 16x16 blocks in 256 colors mode. This codec is also employs exotic bitstream reading: actually you need to read byte and when it's exhausted, read another byte, so flags and other data are very mixed. Two versions of this codec are known: one stores palette in frame, another one also could do this but stores palette in extradata instead. Compression principle is simple: divide frame into sequence of blocks and then either fill it, copy from other position or divide onto four subblocks and do the same.
 
== Palette change frames ==
 
Newer version of KVMC has two palette change methods - via 'xxpc' (palette change) chunk in AVI and via special frames (some files has both!).
 
Frame header consists of two bytes, first one specifies palette start offset (usually 1 or 128) and the second byte is palette block size (= 127 colors). Legal frames have second byte (block size) equal to 8 (or possible 16) when this frames have 0x7F, so this is how they could be distinguished.
 
Next two bytes are zeroes, and the rest of frame data is 127 palette entries packed in 4-tuples.


== Frame structure ==
== Frame structure ==


Frame consists of the next parts: header byte, palette chunk (if needed), compressed blocks.
Frame consists of the next parts: header byte, palette chunk (if needed), block size (1 byte), compressed blocks.


Header byte may have this bits set:
Header byte may have this bits set:
Line 16: Line 24:
  K - is keyframe
  K - is keyframe
  P - palette is present
  P - palette is present
  xx - unknown bits
  xx - unused bits
  MMMM - compression method (only methods 3 and 4 are known)
  MMMM - compression method (only methods 3 and 4 are known)


Details for palette chunk are still unknown.
Palette size is defined in byte 10 of extradata (usually 127 or rarely 255) and is standard R,G,B triplets.
Compressed blocks are decoded with given method until frame is fully decoded.
Compressed blocks are decoded with given method until frame is fully decoded.


== Method 3 for block 8x8 ==
== Method 3 for block 8x8 ==
This is method used in intraframes:
This is method used in intraframes.


   if(!getbit()){
   if(!getbit()){
Line 64: Line 72:


== Method 4 for block 8x8 ==
== Method 4 for block 8x8 ==
<b>[TODO]</b>
This method is used for interframes and has only two differences from method 3:
* 8x8 block can be not only filled with given value or divided into subblocks but also can be skipped;
* motion compensation uses previous frame for reference and has motion vactor range -8..7 instead of -15..0.
 
  if(!getbit()){
    if(!getbit()){
      copy block from previous frame unchanged
    }else{
      val = getbyte();
      fill block 8x8 with val;
    }
  } else {
    for all subblocks 4x4 {
      if(!getbit()){
        if(!getbit()){
          val = getbyte();
          fill block 4x4 with given val;
        } else {
          val = getbyte();
          mx = (val & 0xF) - 8;
          my = (val >> 4) - 8;
          copy block 4x4 from previous frame with offset (mx, my)
        }
      } else {
        for all subblocks 2x2 (in subblock 4x4) {
          if(!getbit()){
            if(!getbit()){
              val = getbyte();
              fill block 2x2 with given val;
            } else {
              val = getbyte();
              mx = val & 0xF;
              my = val >> 4;
              copy block 2x2 from previous frame with offset (mx, my)
            }
          } else {
            block[0,0] = getbyte();
            block[0,1] = getbyte();
            block[1,0] = getbyte();
            block[1,1] = getbyte();
          }
        }
      }
    }
  }


== Method 3 for block 16x16 ==
== Method 3 for block 16x16 ==
<b>[TODO]</b>
Extended method 3 for 8x8 blocks. There are no known samples to test.


== Method 4 for block 16x16 ==
== Method 4 for block 16x16 ==
<b>[TODO]</b>
Extended method 4 for 8x8 blocks. There are no known samples to test.


[[Category:Undiscovered Video Codecs]]
[[Category:Game Formats]]
[[Category:Video Codecs]]
[[Category:Video Codecs]]
[[Category:Game Formats]]

Latest revision as of 02:04, 15 March 2011

KMVC is used on various Worms PC games.

Common details

This codec operates on 8x8 or 16x16 blocks in 256 colors mode. This codec is also employs exotic bitstream reading: actually you need to read byte and when it's exhausted, read another byte, so flags and other data are very mixed. Two versions of this codec are known: one stores palette in frame, another one also could do this but stores palette in extradata instead. Compression principle is simple: divide frame into sequence of blocks and then either fill it, copy from other position or divide onto four subblocks and do the same.

Palette change frames

Newer version of KVMC has two palette change methods - via 'xxpc' (palette change) chunk in AVI and via special frames (some files has both!).

Frame header consists of two bytes, first one specifies palette start offset (usually 1 or 128) and the second byte is palette block size (= 127 colors). Legal frames have second byte (block size) equal to 8 (or possible 16) when this frames have 0x7F, so this is how they could be distinguished.

Next two bytes are zeroes, and the rest of frame data is 127 palette entries packed in 4-tuples.

Frame structure

Frame consists of the next parts: header byte, palette chunk (if needed), block size (1 byte), compressed blocks.

Header byte may have this bits set:

KPxx MMMM
K - is keyframe
P - palette is present
xx - unused bits
MMMM - compression method (only methods 3 and 4 are known)

Palette size is defined in byte 10 of extradata (usually 127 or rarely 255) and is standard R,G,B triplets. Compressed blocks are decoded with given method until frame is fully decoded.

Method 3 for block 8x8

This is method used in intraframes.

 if(!getbit()){
   val = getbyte();
   fill block 8x8 with val;
 } else {
   for all subblocks 4x4 {
     if(!getbit()){
       if(!getbit()){
         val = getbyte();
         fill block 4x4 with given val;
       } else {
         val = getbyte();
         mx = val & 0xF;
         my = val >> 4;
         copy block 4x4 from offset (-mx, -my)
       }
     } else {
       for all subblocks 2x2 (in subblock 4x4) {
         if(!getbit()){
           if(!getbit()){
             val = getbyte();
             fill block 2x2 with given val;
           } else {
             val = getbyte();
             mx = val & 0xF;
             my = val >> 4;
             copy block 2x2 from offset (-mx, -my)
           }
         } else {
           block[0,0] = getbyte();
           block[0,1] = getbyte();
           block[1,0] = getbyte();
           block[1,1] = getbyte();
         }
       }
     }
   }
 }

Method 4 for block 8x8

This method is used for interframes and has only two differences from method 3:

  • 8x8 block can be not only filled with given value or divided into subblocks but also can be skipped;
  • motion compensation uses previous frame for reference and has motion vactor range -8..7 instead of -15..0.
 if(!getbit()){
   if(!getbit()){
     copy block from previous frame unchanged
   }else{
     val = getbyte();
     fill block 8x8 with val;
   }
 } else {
   for all subblocks 4x4 {
     if(!getbit()){
       if(!getbit()){
         val = getbyte();
         fill block 4x4 with given val;
       } else {
         val = getbyte();
         mx = (val & 0xF) - 8;
         my = (val >> 4) - 8;
         copy block 4x4 from previous frame with offset (mx, my)
       }
     } else {
       for all subblocks 2x2 (in subblock 4x4) {
         if(!getbit()){
           if(!getbit()){
             val = getbyte();
             fill block 2x2 with given val;
           } else {
             val = getbyte();
             mx = val & 0xF;
             my = val >> 4;
             copy block 2x2 from previous frame with offset (mx, my)
           }
         } else {
           block[0,0] = getbyte();
           block[0,1] = getbyte();
           block[1,0] = getbyte();
           block[1,1] = getbyte();
         }
       }
     }
   }
 }

Method 3 for block 16x16

Extended method 3 for 8x8 blocks. There are no known samples to test.

Method 4 for block 16x16

Extended method 4 for 8x8 blocks. There are no known samples to test.