# System Architecture

## Process Architecture

The system runs as multiple cooperating processes communicating through shared memory:

      Camera 0 ──> capture.exe 0 ──┐
      Camera 1 ──> capture.exe 1 ──┼──> Shared Memory (16GB) ──> videogen.exe ──> viewer.exe
      Camera 2 ──> capture.exe 2 ──┘         ^                        |
                                              |                        v
                                   motion.exe 0/1/2              Output Files
                                   (reads feeds,                   (H.264 MP4)
                                    writes flags)

      controller.exe: launches and monitors all processes

## Shared Memory Layout

All processes access a single large shared memory region (~16GB) containing:

### Control Region

- Feed count, channel states, frame indices
- Motion detection flags and results
- Movie recording state (start/end frames, type)

### Feed Data (3 feeds x 3 channels x 520 frames)

Each feed has 3 channels (active, latest, ready) with 520-frame circular buffers. Each frame contains:

- 224-byte header (frame number, timestamp, motion data, blob info)
- Y plane: 1920 x 1080 bytes (luminance)
- U plane: 960 x 540 bytes (chrominance)
- V plane: 960 x 540 bytes (chrominance)
- Total per frame: ~2.3 MB

### Output Data (2 output feeds x 520 frames)

Double-buffered output for the viewer. While one buffer is being written by videogen, the viewer reads the other.

### Memory Totals

Component | Calculation | Size
--- | --- | ---
Feed data | 3 feeds x 3 channels x 520 frames x 2.3MB | ~10.8 GB
Output data | 2 feeds x 520 frames x 2.3MB | ~2.4 GB
Control/metadata | Headers, indices, flags | ~50 MB
Total |  | ~13.3 GB

## IPC Mechanism

Processes coordinate through 20 named Windows synchronization objects:

### Named Mutexes

Protect concurrent access to shared data:

Mutex | Purpose
--- | ---
0 | Current frame index update
1 | Source thread frame posting wait
2 | Channel check/increment
3, 4, 5 | Next-write index for feeds 0, 1, 2
6, 7, 8 | Motion detection signal for feeds 0, 1, 2
9 | Output feed and frame count
10 | Frames-this-channel counter
11 | Motion info: min type2 frame
12 | Motion info: movie start
13 | Motion info: movie end
14 | Frame builder broadcast
15 | Index of last frame built
16, 17 | Viewer shared memory access

### Named Events

- Auto-reset events for point-to-point signaling (capture → motion)
- Manual-reset events for broadcast signaling (motion → videogen)

## Data Flow

1. Capture: Reads YUV422 from USB, converts to YUV420, crops to 540 lines, writes to circular buffer, signals motion
2. Motion: Frame differencing, adaptive threshold, binary map, flood-fill blob detection, blob merge, trigger evaluation. Writes results to frame headers.
3. VideoGen: On motion trigger, merges two feeds into composite frame (1920x1080), pipes to FFmpeg for H.264 encoding, optionally uploads
4. Viewer: Copies frames from output buffer to local memory, renders with SDL3, draws grid line overlays, calculates distance at cursor

## Frame Format: YUV420

All frame data is stored as YUV420 planar:

- Y plane: Full resolution (1920x1080 or 1920x540 per crop). One byte per pixel, luminance.
- U plane: Half resolution (960x540 or 960x270 per crop). One byte per 2x2 pixel block, blue chrominance.
- V plane: Half resolution. Red chrominance.

This format halves the data compared to YUV422 and is native to H.264 encoding.

## Circular Buffer

Each feed channel has a 520-frame circular buffer (~8.7 seconds at 60fps). The `next_write` index advances modulo 520. Readers track their own position and must stay within the buffer window or they'll read stale data.

## Feed Merge Compositing

Output frames combine two camera feeds vertically:

Display Type | Top 540 lines | Bottom 540 lines | When Used
--- | --- | --- | ---
Type 0/1 | Feed 1 (middle) | Feed 0 (top of hill) | Jumper in top/middle of hill
Type 2 | Feed 1 (middle) | Feed 2 (bottom of hill) | Jumper past top of hill

## Design Principles

- No dynamic allocation during processing — all memory is allocated at startup and held until shutdown, preventing periodic freeze-ups from garbage collection or heap fragmentation
- Pointer arithmetic in inner loops — sequential memory access for cache efficiency
- Multi-process isolation — each component is a separate process; a crash in one doesn't bring down the system (controller auto-restarts crashed processes)
- Double buffering — output uses two alternating buffers to prevent tearing between writer and reader

## See Also

- System Overview
- Hardware Setup
- Settings Reference