<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.multimedia.cx/index.php?action=history&amp;feed=atom&amp;title=Psygnosis_SMV</id>
	<title>Psygnosis SMV - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.multimedia.cx/index.php?action=history&amp;feed=atom&amp;title=Psygnosis_SMV"/>
	<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=Psygnosis_SMV&amp;action=history"/>
	<updated>2026-06-07T06:22:04Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.5</generator>
	<entry>
		<id>https://wiki.multimedia.cx/index.php?title=Psygnosis_SMV&amp;diff=14024&amp;oldid=prev</id>
		<title>VAG at 09:20, 31 March 2012</title>
		<link rel="alternate" type="text/html" href="https://wiki.multimedia.cx/index.php?title=Psygnosis_SMV&amp;diff=14024&amp;oldid=prev"/>
		<updated>2012-03-31T09:20:52Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;* Extension: smv&lt;br /&gt;
* Company: [[Psygnosis]]&lt;br /&gt;
* Samples: http://cd.textfiles.com/cdaction/cdaction04/FILM/&lt;br /&gt;
&lt;br /&gt;
SMV is a short-lived FMV format used in the PC game [http://www.mobygames.com/game/dos/wipeout Wipeout] by Psygnosis. It employs LZ-like compression to encode 8-bit palettized video and audio.&lt;br /&gt;
&lt;br /&gt;
== File Format ==&lt;br /&gt;
An SMV file consist of a number of chunks with unique [[TwoCC]]. All numbers are little-endian.&lt;br /&gt;
&lt;br /&gt;
  u16 chunkid&lt;br /&gt;
  u16 chunklen&lt;br /&gt;
  u8  payload[chunklen]&lt;br /&gt;
&lt;br /&gt;
=== ST chunk ===&lt;br /&gt;
File header. Encodes basic movie properties.&lt;br /&gt;
&lt;br /&gt;
  u16 width           -- movie width&lt;br /&gt;
  u16 height          --  and height&lt;br /&gt;
  u16 mbwidth         -- macroblock width&lt;br /&gt;
  u16 mbheight        --  and height&lt;br /&gt;
  u16 frames          -- number of video frames&lt;br /&gt;
  u16 colors          -- number of used colors&lt;br /&gt;
  u16 nibbles         -- offset of frame's nibble data&lt;br /&gt;
  -- if chunk size is &amp;gt;= 15&lt;br /&gt;
  u8  codec           -- video codec format&lt;br /&gt;
&lt;br /&gt;
* Codec field may be absent, in such case assume codec 0.&lt;br /&gt;
* mbwidth is always 16, mbheight may be either 16 or 8.&lt;br /&gt;
* Movie playback rate is 12 FPS.&lt;br /&gt;
&lt;br /&gt;
=== GP chunk ===&lt;br /&gt;
New palette. Contains a number of 6-bit [[RGB]] entries, as specified in ST chunk.&lt;br /&gt;
&lt;br /&gt;
=== MU chunk ===&lt;br /&gt;
Sound chunk. Contains audio fragment in 15862Hz, 8-bit, unsigned, mono format. If the payload size is equal to the amount of audio data for a frame (i.e. the size is freq / fps, which is equal to 1321) then the audio data is stored in raw [[PCM]] format. Otherwise, it's additionally LZ-word-packed.&lt;br /&gt;
&lt;br /&gt;
=== FR chunk ===&lt;br /&gt;
Frame chunk. Contains encoded video frame.&lt;br /&gt;
&lt;br /&gt;
=== FE chunk ===&lt;br /&gt;
End of the movie. No payload.&lt;br /&gt;
&lt;br /&gt;
== Video Compression ==&lt;br /&gt;
&lt;br /&gt;
=== Video Codec 0 ===&lt;br /&gt;
&lt;br /&gt;
 LZUnpack(payload, temp, words)&lt;br /&gt;
 DrawBlocks(temp)&lt;br /&gt;
&lt;br /&gt;
=== Video Codec 1 ===&lt;br /&gt;
&lt;br /&gt;
 LZUnpack(payload, temp, bytes)&lt;br /&gt;
 DrawBlocks(temp)&lt;br /&gt;
&lt;br /&gt;
=== Video Codec 2 ===&lt;br /&gt;
&lt;br /&gt;
 LZUnpack(payload, temp, bytes)&lt;br /&gt;
 UnpackPartitions(temp, temp2)&lt;br /&gt;
 DrawBlocks(temp2)&lt;br /&gt;
&lt;br /&gt;
UnpackPartitions decodes Macroblock's nibbles.&lt;br /&gt;
&lt;br /&gt;
Source frame is broken on to several equal partitions, 2 across by 4 down. Encoded partitions format:&lt;br /&gt;
&lt;br /&gt;
  u8  pixels[16 * num_mblocks]          -- passed as is to DrawBlocks()&lt;br /&gt;
  for each partition&lt;br /&gt;
    u8  codebook[256][2]                -- nibbles codebook for each partition&lt;br /&gt;
  for each partition&lt;br /&gt;
    for each macroblock&lt;br /&gt;
      u8  index[mb_width*mb_height/4]   -- index of codebook entry&lt;br /&gt;
&lt;br /&gt;
Each entry of codebook encodes 4 nibbles. First byte encodes two nibbles of upper macroblock's line, second - next line, and so on.&lt;br /&gt;
&lt;br /&gt;
=== Video Codec 3 ===&lt;br /&gt;
This codec is never used, but the code is still in place.&lt;br /&gt;
&lt;br /&gt;
 if GetByte()&lt;br /&gt;
   LZUnpack(payload, temp, bytes)&lt;br /&gt;
   UnpackSpecial(temp, temp2)&lt;br /&gt;
   DrawBlocks(temp2)&lt;br /&gt;
 else&lt;br /&gt;
   same as codec 1&lt;br /&gt;
&lt;br /&gt;
UnpackSpecial performs advanced decompression. '''TODO''' ''this may be some common algorithm''&lt;br /&gt;
&lt;br /&gt;
=== Macroblocks drawing ===&lt;br /&gt;
Macroblocks are stored in the following format:&lt;br /&gt;
&lt;br /&gt;
  u8 pixels[16 * num_mblocks]&lt;br /&gt;
  u4 nibbles[num_mblocks]&lt;br /&gt;
&lt;br /&gt;
Size of pixels[] is equal to ST chunk's ''nibbles''.&lt;br /&gt;
For each macroblock draw it by indexing its pixels by nibbles. First nibble stored in top 4 bits of byte.&lt;br /&gt;
&lt;br /&gt;
== Common Algorithms ==&lt;br /&gt;
=== LZ decompression ===&lt;br /&gt;
This is a more-or-less common LZ77-like algorithm. It can operate in two modes: byte mode and words mode. Mode affects backchain offset encoding.&lt;br /&gt;
* &amp;quot;next bit&amp;quot; means next bit from the internal 8-bit bitreader queue. Queue refilled with the input stream bytes, bits are consumed starting from the highest.&lt;br /&gt;
* &amp;quot;next byte&amp;quot; means raw octet from the input stream&lt;br /&gt;
&lt;br /&gt;
  repeat&lt;br /&gt;
 &lt;br /&gt;
    if next bit == 0&lt;br /&gt;
      output next byte&lt;br /&gt;
    else&lt;br /&gt;
      if next bit == 0&lt;br /&gt;
        offset = next byte&lt;br /&gt;
      else&lt;br /&gt;
        if byte mode&lt;br /&gt;
          offset = next 3 bits || next byte  + 1&lt;br /&gt;
        if words mode&lt;br /&gt;
          offset = next 2 bits || next byte  + 1  *2&lt;br /&gt;
 &lt;br /&gt;
      if next bit == 0        length = 2&lt;br /&gt;
      else if next bit == 0   length = 3 + next bit&lt;br /&gt;
      else if next bit == 0   length = 5 + next bit&lt;br /&gt;
      else if next bit == 0   length = 7&lt;br /&gt;
      else if next byte != 0  length = 7 + this byte&lt;br /&gt;
      else finish unpacking&lt;br /&gt;
 &lt;br /&gt;
      copy length bytes from output - offset to output&lt;br /&gt;
       note that, bytes may overlap to repeat itself&lt;br /&gt;
&lt;br /&gt;
[[Category:Game Formats]]&lt;br /&gt;
[[Category:Video Codecs]]&lt;br /&gt;
[[Category:Formats missing in FFmpeg]]&lt;/div&gt;</summary>
		<author><name>VAG</name></author>
	</entry>
</feed>