This page compiles a small computation into a standard H.264 video stream. After a few start-up frames, the stream repeats the same 16 instruction frames, and each decoded picture supplies the state for the next step. Change the input, and watch your browser's video decoder run it.
JavaScript builds and feeds the stream. The H.264 decoder updates the running state.
1Input
starting pattern · 200 × 200 cells · edges wrap
Click or drag to draw; start a drag on a live cell to erase. Keyboard: arrow keys move (Shift for 10), Space toggles, Enter runs. A preset runs at once.
1Input
the registers at the start
Michael Fryers' prime program and its constants. Each word is MOV Rd, Rs: destination in the high byte, source in the low. Execution starts at R1, with one branch delay slot.
2Repeated instructions
– each. From frame – on, the decoder gets only these 16 frames, in turn, forever. They are identical except for a 4-bit frame counter, so they cannot carry the changing state.
The state lives in the decoder's reference pictures: each decoded frame is read by the next ones.
3Output, decoded by your browser
generation 0
Writing the stream…
Starting…
The same stream as an ordinary MP4. Open it in a standalone player, such as VLC, QuickTime or mpv, and that player's decoder computes the same run, for as long as the file lasts.
How the frame stores the machine
4032 × 832 · the same frames
This is the whole decoded frame, live, as your decoder outputs it, before the crop that players apply. No contrast stretching. A cell field holds the same number in all three colour planes, which a player shows as green for 0 through grey to magenta for 255. Each outlined region is one field, a board of cells that one weighted prediction rewrites every frame.
Where the next state comes from
What your decoder is fed
JavaScript writes the first frames once: the starting state, as raw samples, then copies so that every delay in the program can read it. After that it only hands your decoder the 16 compiled program frames, over and over, through WebCodecs. The page keeps no copy of the state; it lives in the decoder's reference frames.
Access units
Coded as
What they carry
Bytes
How the decoder computes a generation
H.264 builds a B-frame macroblock by copying blocks from earlier frames and mixing them with explicit weights: clip(((w0·a + w1·b + 2L) >> (L+1)) + o). Each field below is a 200 × 200 board in its own region of the frame, rewritten every frame by one such mix, and motion vectors choose the cells it reads. One generation takes 6 frames, so at 60 frames a second the board advances 10 times a second. Flat out, it advances as fast as your decoder decodes.
Field
Weighted prediction
Value
p1 … p4
(8·a + 8·b + 64) >> 7, L = 6
16 per live neighbour, two neighbours each
p5
(2·a + 32) >> 6, L = 6
8 if the cell itself is alive
q1, q2, c
a + b, then a + b − 16
16 × neighbours − 16
t
c + p5 (p5 read 3 frames back)
16 × neighbours + 8 × alive − 16
ge24, ge48
steep weights against a constant field
255 if t ≥ 24, 255 if t ≥ 48
S
ge24 − ge48
alive next ⇔ 24 ≤ t ≤ 40 ⇔ 3 neighbours, or 2 and alive
d, H
relu(0.8·H − S), then S + d
a glow: max(alive, 0.8 × last generation's glow)
r0, r1, D
two ramps, one three-colour mix at L = 6
the coloured board, at the frame's top-left corner
T
(62·a + 32) >> 6 − 1, a at a quarter-pixel offset
1920 × 1080 around the board: each macroblock copies the previous frame from 3% nearer the centre, turned back 0.8°, so the decoder interpolates; aging streaks fade and drift blue
How the decoder executes an instruction
H.264 builds a B-frame macroblock by copying blocks from earlier frames and mixing them with explicit weights. With weights 2 and 2 the mix of two fields of 0s and 255s is clip(a + b), an OR; with 2 and −2 it is clip(a − b), a AND NOT b. Every field here is 16 × 64 cells: bit k of register r is cell (r, k), so the register bank is one field. The motion vectors are fixed, so the circuit cannot point at a register: it reads all 64 and keeps the one the instruction names, by masking its row and ORing the rows together with a butterfly of shifts. Rotating is reading one column over, because the board wraps round. The adder's carries run round the columns too, which gives ones' complement's end-around carry for free. The circuit is 334 fields, and its longest path is 17 frames, so one instruction takes 17 frames. The display is part of the circuit: it turns the word into decimal digits and draws their segments.