Archive for the ‘ARMovie’ Category

ARMovie: trying codec wrappers

Tuesday, May 7th, 2024

I’ve managed to locate two ARMovie samples with video format 600 and 602 (which is M$ Video 1 and Cinepak correspondingly), so I got curious if I can decode them. The problem is that ARMovie stores video data clumped together in a large(r) chunks so you need to parse frame somehow in order to determine its length.

Luckily in this case the wrapped codec data has 16-byte header (first 32-bit word is either frame size or a special code for e.g. palette or a skipped frame, followed by some unknown value and real codec width and height) so packetising data was not that hard. The only problem was that Video 1 stream was 156×128 while the container declared it as 160×128 but after editing the header it worked fine.

Supporting such wrappers actually poses more of a question of design for NihAV—how to link those rather container-specific packetisers to a demuxer. Making demuxer parse all possible formats is rather stupid, my current solution of simply registering global packetiser and hoping there’s no need for another is a bit hacky. I should probably make it namespaced so that the code first probes e.g. “armovie/cinepak” packetiser before “cinepak” one but it’s an additional effort for no apparent gain. Speaking of which, I should probably change code to feed the stream provided by the packetiser to a decoder (instead of always using the one from demuxer) but since I’m lazy I’m not going to do that either.

Anyway, I’m not going to spend more time on ARMovie unless new samples for the formats I don’t support show up (beside newer Eidos Escape codecs which are supported elsewhere already). There are other formats left to look at. For example, I’ve made a good progress with Adorage animation format.

ARMovie: Moving Blocks done

Tuesday, April 30th, 2024

I’ve finally finished Moving Blocks HQ and REing Super Moving Blocks. The main changes from vanilla Moving Blocks is a larger MV table (vectors can now target as far as 8 pixels instead of previous 4 and the fact that now raw luma samples use delta coding and static Huffman codebook. The only difference between two newer variations is that Super Moving Blocks uses 6-bit luma samples (and larger codebook for handling twice as many possible delta values).

With this part done, all is left is adding support for various Escape codecs as well as raw audio and video formats. And ACEFilm of course, but that’s a separate format.

A quick look at Eidos Escape codecs

Sunday, April 28th, 2024

As people remember, Eidos started as a company offering video editing software for Acorn RISC machines (do not confuse with Acorn RISC Machines company), but later it merged with a game publisher (more than once) and now it’s a Japanese game company. Yet the codecs they developed survived for some time in the games.

Since I was looking at ARMovie and found decompressors for Escape 100 and 102 codecs (essentially the earliest in the series) I looked at those as well and here’s a brief overview.

Both codecs are almost identical in design (only the luma code seems to differ), they operate on 160×128 frames in 5-bit YUV420 format, operating on 2×2 blocks. Chroma values are picked from the table of 256 combined U/V values. The codecs code data as a variable-length code for the number of blocks to skip (the same code seems to have survived until Escape 124) and the following block update mode (luma and/or chroma). As I said before, chroma values are taken from the table or left intact from the previous frame; luma values are coded two 5-bit values and 3-bit mask telling which value to use for the block elements (first element in the block is always the first value of course).

And that’s it. No other modes, the only frame header is 32-bit word with codec ID (later revisions decided to add frame size and even flags that affect decoding process). Nevertheless it’s rather interesting to encounter codecs that use simple two-colour vector quantisation (and fixed codebook for chroma pairs) without any additional image transformation tricks (e.g. motion compensation beside skipping, or even allowing raw blocks).

ARMovie: towards NihAV support

Saturday, April 27th, 2024

Since I had nothing better to do I’ve documented various ARMovie codecs in The Wiki. Essentially what’s left is to document newer Moving Blocks variants (and implement a decoder for one with samples), early Eidos Escape codecs (no idea where to find samples for them though). Also there’s Iota Software codec 500 which has no samples but looks like it’s used primarily in ACE Film format so figuring out nuances of LZW compression there may help with yet another obscure format.

From the technical side the most annoying thing is that data is stored in multiple frames in a single chunk without any kind of size, separator or frame end marker being present. The original player simply expected decoders to report number of bytes consumed after decoding a frame. Which means packetisers that should parse the stream in the same way as decoders do and report the frame size—nothing too complex but still annoying (and I had to augment NAPacketiser API to take reported stream details into account, otherwise it has no way to know frame dimensions). The worst one was Moving Blocks parser. The main problem is that unlike most of the formats this one has frames not aligned to 16 bits—while video chunks are—so it has to deal with possible padding byte at the end of chunk.

Another annoying thing I haven’t really dealt with is detecting all those various sound formats from the format string.

I don’t know if I bother adding various raw video formats support but in either case I don’t regret looking at ARMovie. Even simple codecs turned out to be not so simple and sometimes with interesting peculiarities like run of colour pairs and even four-colour pattern painting in what should’ve been a simple RLE codec.

Acorn Moving Blocks variants

Wednesday, April 24th, 2024

Implementing decoders in NihAV goes slowly since ARMovie essentially stores track data all clumped together and requires a packetiser to split it into video frames. Of course it can always get worse: Actimagine VX stored audio data right after video frame data without storing video part size so you can decode audio only after you’ve decoded video part of the frame. Anyway, I’ve managed to hack a demuxer and even a working Moving Lines decoder. Before tidying it all up and implementing other decoders, I want to give an overview of other Acorn video codecs.

Surprisingly enough, Moving Blocks has some documentation (from the authoritative source nonetheless!). Of course it contains some minor mistakes, mostly some values in motion vectors table (some values have their minus sign forgotten and the order or some values for spacial copy vectors is wrong).

For those who’re simultaneously too lazy to read the description and curious enough to know how the codec functions, it’s simple: frames are split into 4×4 blocks, each block has a variable-length code for its coding mode—raw data (subsampled YUV apparently), motion compensated block (with a variable-length motion vector pointing to a previous frame or an already decoded part of the current frame) or split into 2×2 blocks with either raw or motion-compensated mode.

But that’s not all, the codec got development as Moving Blocks HQ. I have not fully analysed it yet but the main changes that now motion vector table is four times larger and includes extended range motion vectors, there’s no longer raw mode for 4×4 blocks (it got replaced with a dedicated skip mode) and raw 2×2 blocks use static Huffman coding (or at least it looks like that; also maybe it uses delta coding but I’m really unsure about that).

And of course they did not stop on that and created Super Moving Blocks. From what I can see it has a larger Huffman codebook plus slightly different modes (like skip modes for 2×2 blocks). I was unable to locate samples for it so it’s a theoretical exercise.

Apparently there was also yet another attempt called Moving Blocks Beta but since I could not find a decoder for it, we can only speculate what changes it had.

At least there will be something to document on The Wiki when I’m done with all this.

Update: now as I have a working decoder, I can say that I was wrong about some things in Moving Blocks. The specification is correct except for some motion values. As for the later revisions of the codec, I’ll postpone them as REing them will involve manual decompilation. Luckily for me there are more codecs to look at.

ARMovie: Moving Lines codec

Monday, April 22nd, 2024

While I’m trying to write a decent demuxer for the format, here’s the description of the first codec for it (I’ll postpone the rest until I implement a demuxer and a decoder for this one).

So, Moving Lines (aka codec 1) works on the usual 15-bit pixels and packs data into 16-bit words (sadly Ghidra fails to realise that LDR loads 16-bit data on ARMv4 but I’ll manage). Bits are read LSB first.

Here are patterns for the opcodes: first (low) bit signals a special code and when unset the rest of the word is a raw pixel. For special codes it’s easier to look at the top bits first though.

  • 0x0001..0x8FFF—copy the amount of pixels stored in the next 6 bits using displacement table (from -8,-8 to 8,8 excluding 0,0) with table index stored in the following 9 bits;
  • 0x9001..0xE5FF—copy data from the already decoded part of current frame, next 6 bits are amount of pixels to copy, the following 8 bits code the displacement (from -9,-9 to 9,0);
  • 0xE601—end of frame marker
  • 0xE603..0xEFFF—run series, 10 bits code run length minus one and the next codeword is pixel value;
  • 0xF001..0xF7FF—skip series, 10 bits code skip length minus one;
  • 0xF801..0xFFFF—raw data values, 10 bits code code number of values, the following codewords contain packed 15-bit values. In the end bitstream is aligned to 16-bit boundary.

Since video data is usually clumped together in large chunks you need to keep decoding it until you encounter end-of frame marker (and then data for the following frame starts).

That’s all for now, hopefully more will come soon.

Starting to look at ARMovie

Saturday, April 20th, 2024

So while looking at various exotic formats, I decided to look at the other video format family from the A-class of computers. This time not Amiga but Acorn (so far nobody has updated Amiga binary loaders for Ghidra 11, I feel more and more that upgrading for 10.x series was a mistake). So, Acorn Replay Movie format for a computer using Acorn RISC Machine CPU.

For those who do not know, the format has human-readable header and may contain several audio and video streams in various formats. And it had a variety of video codecs supported from different vendors—raw YUV or RGB formats, repacked formats (like MPEG, Quicktime or M$ Video-1 and RLE) and some original ones. Apparently people cared only about some later codecs developed by Eidos Technologies as they were used in their PC games as well but there is more to it.

My search resulted in the following list of codecs (raw video codecs are omitted; also while many entries come from the official documentation, not all of them do):

  • 1—Acorn Moving Lines;
  • 7—Acorn Moving Blocks;
  • 12-13—MPEG wrapper (inside RPL or as a reference to an external file);
  • 14—IBM Ultimotion;
  • 17—Acorn Moving Blocks HQ;
  • 18—H.263;
  • 19—Acorn Super Moving Blocks;
  • 20—Acorn Moving Blocks Beta
  • 100, 102, 122, 124, 130—Eidos Escape codecs (but hardly anybody cares about the first two of those);
  • 500—LZW-compressed frames from Iota Software;
  • 600—M$ Video-1 8-bit;
  • 601—M$ Video-1 15-bit;
  • 602—Cinepak;
  • 603—QuickTime RPZA;
  • 604—QuickTime SMC;
  • 605—IBM Ultimotion (again);
  • 607—M$ RLE 8-bit;
  • 609—QuickTime 8-bit RLE;
  • 610—FLIC;
  • 613-615—QuickTime RLE, 4-, 16- and 24-bit variants respectively;
  • 622—WSS DL (in reality just palette plus raw pixels);
  • 623—ANM film wrapper;
  • 630—QuickTime VR wrapper;
  • 800—LinePack by Henrik Bjerregaard Pedersen
  • 802—Movie 16:3 by the same developer (apparently something similar to codecs like Video-1)
  • 803—a generic AVI/QT/FLI codec wrapper from the same developer.

The decoder format is well-documented so you just need to load raw binary to Ghidra without much hassle and you know what parameters to expect as well. I’ve actually looked at some of those codecs already and willing to continue.

So probably I’ll waste some indefinite time adding ARMovie support to NihAV with various codecs nobody cares about (and/or documenting them). I have not located samples for many of the formats but at least I’ve found some for codecs 1, 7, 17 and 800 which seem to be some of the most interesting ones.