rainbow-dragon/docs/research/red-rcp2-protocol.md

75 lines
3.8 KiB
Markdown

# RED RCP2 Protocol — verified findings
Sources:
- `kjayasa/commander``components/rcp/rcp.cpp`: full RCP2 parameter table (293 params w/ types + supported JSON ops), extracted from official RED docs (910-0327 protocol + per-camera parameter PDFs)
- `intGus/komodo-remote``code.py`: working client against real Komodo, exact wire format
## Transport (corrects our v1 driver)
- **WebSocket**, `ws://<camera_ip>:9998/rcp` — NOT raw TCP, NOT length-prefixed
- Text frames, one JSON object per frame
- Camera can push unsolicited notifications (e.g. RECORD_STATE changes)
## Handshake
First message after connect:
```json
{"type":"rcp_config","strings_decoded":0,"json_minified":1,
"include_cacheable_flags":0,"encoding_type":"html",
"client":{"name":"Forge"}}
```
Camera replies once; then normal traffic.
## Messages
- Get: `{"type":"rcp_get","id":"RECORD_STATE"}`
- Set: `{"type":"rcp_set","id":"RECORD_STATE","value":"2"}`
- Param IDs = `RCP_PARAM_*` names **with `RCP_PARAM_` prefix stripped**
- Response/notification: `{"id":"RECORD_STATE","cur":{"val":<int>}, ...}` — value under `cur.val`
- Other ops exist: `rcp_get_list`, `rcp_get_status`, `rcp_notification`, `rcp_subscribe` (see rcp.cpp enum)
## Parameters we use
| Purpose | Param (wire id) | Type |
|---|---|---|
| Rec state | `RECORD_STATE` | value; 0=idle 1=recording 2=toggle-request |
| Clip name | `CLIP_NAME` | status |
| ISO/EI | `ISO` | value |
| White balance | `COLOR_TEMPERATURE` | value |
| Tint | `TINT` | value |
| FPS | `SENSOR_FRAME_RATE` | value |
| Timecode | `TIMECODE` | status |
| CDL enable | `CDL_ENABLE` | value |
| CDL slope | `CDL_SLOPE_RED/GREEN/BLUE` | value (per channel!) |
| CDL offset | `CDL_OFFSET_RED/GREEN/BLUE` | value |
| CDL power | `CDL_POWER_RED/GREEN/BLUE` | value |
| CDL sat | `CDL_SATURATION` | value |
| Active LUT name | `APPLIED_CAMERA_LUT` | status (read-only) |
| Select camera LUT | `CAMERA_LUT` | value (selects from camera's stored list) |
| Import LUT from media | `MEDIA_LUT_IMPORT_TO_CAMERA` | action |
## Capability corrections for our driver
1. **CDL is per-channel scalar params**, not a JSON blob. 10 sets per full CDL push (9 SOP + sat). CDL_ENABLE=1 required.
2. **No live 3D LUT upload over RCP2.** `CAMERA_LUT` only selects LUTs already on camera; `MEDIA_LUT_IMPORT_*` pulls from inserted media. So RED live-grade path = **native CDL only**; creative LUT must be pre-loaded to camera or baked into monitor path elsewhere.
→ capabilities: `supportsNativeCDL=true`, `lut3dSizes=[]`.
3. Gang: for RED slots, only the leading-CDL portion of a node stack is pushable live. Remainder LUT must be identity, else surface a warning state (grade preview ≠ camera monitor).
# ASC MHL v2.0 — verified findings
Source: `ascmitc/mhl-specification` + reference impl `ascmitc/mhl` (XSD fetched, stored below).
Corrections to our v1 MHL writer:
- Root: `<hashlist version="2.0" xmlns="urn:ASC:MHL:v2.0">`
- Required: `<creatorinfo>` (creationdate, hostname, tool) AND `<processinfo>` (process ∈ in-place|transfer|flatten)
- Hash entries: `<hash><path size="..." lastmodificationdate="...">rel/path</path><xxh64 action="original|verified|failed" hashdate="...">hex</xxh64></hash>`
— size is an ATTRIBUTE of path, hash algo is element name, action attribute tracks chain state
- Folder convention: manifests live in `ascmhl/` subfolder, named `NNNN_<foldername>_<date>.mhl`, plus `ascmhl_chain.xml`
- Directory hashes optional (content + structure)
XSD: https://raw.githubusercontent.com/ascmitc/mhl/master/xsd/ASCMHL.xsd
# Other useful repos found
- `ascmitc/mhl` — Python reference impl, good for cross-validation of our manifests
- Tangent Hub: no public TIPC repos of note; Tangent's official "Tangent Hub" SDK ships the mapping XML + TIPC docs with the installer (macOS phase task)