Add serial/protocol modules to plan, binary format to arch, -flto to Makefiles
architecture.md: replace JSON control payloads with binary serialization; add Protocol Serialization section describing little-endian wire format, put/get buffer layer, and write_*/read_* protocol layer. planning.md: mark common/media_ctrl/v4l2_ctrl done; insert serial (#4) and protocol (#6) modules with descriptions. conventions.md: document -flto and its implication (no manual static for inlining — compiler handles it at link time). Makefiles: add -flto to CFLAGS in all four Makefiles. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -125,10 +125,10 @@ Header fields:
|
|||||||
| Value | Meaning |
|
| Value | Meaning |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `0x0001` | Video frame |
|
| `0x0001` | Video frame |
|
||||||
| `0x0002` | Control request (JSON) |
|
| `0x0002` | Control request |
|
||||||
| `0x0003` | Control response (JSON) |
|
| `0x0003` | Control response |
|
||||||
|
|
||||||
Video frame payloads are raw compressed frames. Control payloads are JSON — the same request/response structure as the V4L2 RPC protocol, but carried inline on the same connection rather than on a separate port.
|
Video frame payloads are raw compressed frames. Control payloads are binary-serialized structures — see [Protocol Serialization](#protocol-serialization).
|
||||||
|
|
||||||
### Unified Control and Video on One Connection
|
### Unified Control and Video on One Connection
|
||||||
|
|
||||||
@@ -248,6 +248,35 @@ The final deliverable is a single configurable node binary. During development,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Protocol Serialization
|
||||||
|
|
||||||
|
Control message payloads use a compact binary format. The wire encoding is **little-endian** throughout — all target platforms (Raspberry Pi ARM, x86 laptop) are little-endian, and little-endian is the convention of most modern protocols (USB, Bluetooth LE, etc.).
|
||||||
|
|
||||||
|
### Serialization Layer
|
||||||
|
|
||||||
|
A `serial` module provides the primitive read/write operations on byte buffers:
|
||||||
|
|
||||||
|
- `put_u8`, `put_u16`, `put_u32`, `put_i32`, `put_u64` — write a value at a position in a buffer
|
||||||
|
- `get_u8`, `get_u16`, `get_u32`, `get_i32`, `get_u64` — read a value from a position in a buffer
|
||||||
|
|
||||||
|
These are pure buffer operations with no I/O. Fields are never written by casting a struct to bytes — each field is placed explicitly, which eliminates struct padding and alignment assumptions.
|
||||||
|
|
||||||
|
### Protocol Layer
|
||||||
|
|
||||||
|
A `protocol` module builds on `serial` and the transport to provide typed message functions:
|
||||||
|
|
||||||
|
```c
|
||||||
|
write_v4l2_set_control(stream, id, value);
|
||||||
|
write_v4l2_get_control(stream, id);
|
||||||
|
write_v4l2_enumerate_controls(stream);
|
||||||
|
```
|
||||||
|
|
||||||
|
Each `write_*` function knows the exact wire layout of its message, packs the full frame (header + payload) into a stack buffer using `put_*`, then issues a single write to the stream. The corresponding `read_*` functions unpack responses using `get_*`.
|
||||||
|
|
||||||
|
This gives a clean two-layer separation: `serial` handles byte layout, `protocol` handles message semantics and I/O.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
- What is the graph's representation format — in-memory object graph, serialized config, or both?
|
- What is the graph's representation format — in-memory object graph, serialized config, or both?
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
- **C11** throughout (`-std=c11`)
|
- **C11** throughout (`-std=c11`)
|
||||||
- **`_GNU_SOURCE`** defined via `-D_GNU_SOURCE` in all Makefiles — enables the full GNU/Linux feature set (POSIX 2008, BSD, GNU and Linux-specific extensions); do not define this in source files
|
- **`_GNU_SOURCE`** defined via `-D_GNU_SOURCE` in all Makefiles — enables the full GNU/Linux feature set (POSIX 2008, BSD, GNU and Linux-specific extensions); do not define this in source files
|
||||||
|
- **LTO enabled** via `-flto` in all Makefiles — the compiler handles inlining across translation units at link time; do not use `static` on functions solely to enable inlining
|
||||||
- Target platform: Linux (V4L2, epoll, etc. are Linux-specific)
|
- Target platform: Linux (V4L2, epoll, etc. are Linux-specific)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ROOT := $(abspath ../..)
|
ROOT := $(abspath ../..)
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -I$(ROOT)/include
|
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -flto -I$(ROOT)/include
|
||||||
BUILD = $(ROOT)/build
|
BUILD = $(ROOT)/build
|
||||||
|
|
||||||
COMMON_OBJ = $(BUILD)/common/error.o
|
COMMON_OBJ = $(BUILD)/common/error.o
|
||||||
|
|||||||
18
planning.md
18
planning.md
@@ -37,14 +37,16 @@ Modules are listed in intended build order. Each depends only on modules above i
|
|||||||
|
|
||||||
| # | Module | Status | Notes |
|
| # | Module | Status | Notes |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 1 | `common` | not started | Error types, base definitions — no dependencies |
|
| 1 | `common` | done | Error types, base definitions — no dependencies |
|
||||||
| 2 | `media_ctrl` | not started | Media Controller API — device and topology enumeration, pad format config |
|
| 2 | `media_ctrl` | done | Media Controller API — device and topology enumeration, pad format config |
|
||||||
| 3 | `v4l2_ctrl` | not started | V4L2 controls — enumerate, get, set camera parameters |
|
| 3 | `v4l2_ctrl` | done | V4L2 controls — enumerate, get, set camera parameters |
|
||||||
| 4 | `transport` | not started | Encapsulated transport — header encode/decode, framed TCP read/write |
|
| 4 | `serial` | not started | `put`/`get` primitives for little-endian binary serialization into byte buffers |
|
||||||
| 5 | `frame_alloc` | not started | Per-frame allocation with bookkeeping (byte budget, ref counting) |
|
| 5 | `transport` | not started | Encapsulated transport — frame header, TCP stream abstraction, single-write send |
|
||||||
| 6 | `relay` | not started | Input dispatch to output queues (low-latency and completeness modes) |
|
| 6 | `protocol` | not started | Typed `write_*`/`read_*` functions for all message types; builds on serial + transport |
|
||||||
| 7 | `ingest` | not started | MJPEG frame parser (two-pass EOI state machine, opaque stream → discrete frames) |
|
| 7 | `frame_alloc` | not started | Per-frame allocation with bookkeeping (byte budget, ref counting) |
|
||||||
| 8 | `archive` | not started | Write frames to disk, control messages to JSON log |
|
| 8 | `relay` | not started | Input dispatch to output queues (low-latency and completeness modes) |
|
||||||
|
| 9 | `ingest` | not started | MJPEG frame parser (two-pass EOI state machine, opaque stream → discrete frames) |
|
||||||
|
| 10 | `archive` | not started | Write frames to disk, control messages to binary log |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ROOT := $(abspath ../../..)
|
ROOT := $(abspath ../../..)
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -I$(ROOT)/include
|
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -flto -I$(ROOT)/include
|
||||||
BUILD = $(ROOT)/build/common
|
BUILD = $(ROOT)/build/common
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ROOT := $(abspath ../../..)
|
ROOT := $(abspath ../../..)
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -I$(ROOT)/include
|
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -flto -I$(ROOT)/include
|
||||||
BUILD = $(ROOT)/build/media_ctrl
|
BUILD = $(ROOT)/build/media_ctrl
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ROOT := $(abspath ../../..)
|
ROOT := $(abspath ../../..)
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -I$(ROOT)/include
|
CFLAGS = -std=c11 -Wall -Wextra -D_GNU_SOURCE -flto -I$(ROOT)/include
|
||||||
BUILD = $(ROOT)/build/v4l2_ctrl
|
BUILD = $(ROOT)/build/v4l2_ctrl
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|||||||
Reference in New Issue
Block a user