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

3.8 KiB

RED RCP2 Protocol — verified findings

Sources:

  • kjayasa/commandercomponents/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-remotecode.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:

{"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)