Skip to content

HDR (HLG) camera streaming — stage 1#80

Merged
MyNamesEMurray merged 4 commits into
mainfrom
claude/init-lklchz
Jul 25, 2026
Merged

HDR (HLG) camera streaming — stage 1#80
MyNamesEMurray merged 4 commits into
mainfrom
claude/init-lklchz

Conversation

@MyNamesEMurray

Copy link
Copy Markdown
Owner

What & why

Adds opt-in 10-bit HDR camera streaming, end to end: the app captures HLG (x420, BT.2020) and hardware-encodes HEVC Main10 with the correct colour tags in the bitstream; the plugin decodes it and renders it correctly on both the standard async path (new yuv420p10 → I010 mapping plus the frame's transfer function, which was never being set — a latent bug that also mis-rendered hardware P010) and the GPU-pipeline beta (10-bit CPU upload with new HLG shader techniques and an extended-range colour-space report). Off by default; HEVC-only; degrades to SDR rather than ever producing a black stream.

Built with stage 2 (zero-copy 10-bit GPU pipeline) and Apple Log capture in mind: colour is an enum (StreamColor) not a boolean, gpu_frame_map_result now carries a pixel-format enum, the wire signal is an extensible "color" field on VIDEO_CONFIG (spec'd in docs/PROTOCOL.md; absent = SDR, bitstream VUI stays authoritative), and the zero-copy mappers explicitly refuse 10-bit hardware surfaces so they take the CPU path instead of rendering garbage.

Also in this PR: STATE advertises "hdr": true and an HEVC-only codec list while HLG is active (remote UIs refuse H.264 through the existing set_format validation, no web-panel changes needed), the Camera diagnostics table gains a colour column (10bit/8bit, HLG, Log), and docs updates (PROTOCOL, PERFORMANCE, README).

How it was tested

  • Decode harness driving the real h264-decoder.c with a generated HEVC Main10 BT.2020/HLG bitstream: before frames=0 (dropped as unsupported), after frames=18 format=I010 cs=2100-HLG trc=hlg; the SDR H.264 sample is byte-identical to its baseline.
  • Plugin builds clean with -Wall -Wextra -Werror (Linux); Swift sources parse clean via syntax-check.sh.
  • Needs a live device test: HDR toggle on an iPhone that supports Main10 (Options → HDR), checked against both an SDR and an HDR OBS canvas, plus one SDR regression pass with the toggle off. Shader techniques for the GPU-pipeline beta can't be exercised in CI at all.

🤖 Generated with Claude Code

https://claude.ai/code/session_015dWUcqAkNNuNELnMPS4RdT


Generated by Claude Code

claude added 4 commits July 25, 2026 08:31
"color": "hlg" (10-bit HEVC, BT.2020 + HLG) with "log" reserved for
Apple Log; absent = 8-bit SDR BT.709, which every stream was before the
field existed. Informational by design -- the decoder takes the
authoritative colour description from the bitstream VUI, so receivers
that ignore the field render correctly; it exists so UIs can label the
stream without decoding it. HDR is HEVC-only and camera-only.

Spec lands ahead of the implementation (stage 1 in progress).

Release-Skip: true

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015dWUcqAkNNuNELnMPS4RdT
README gains the HDR (beta) feature bullet; PERFORMANCE.md's "wire is
8-bit" divergence note becomes "defaults to 8-bit", pinning the rule
that SDR, screen mirror, and H.264 stay free of 10-bit branches.

Release-Skip: true

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015dWUcqAkNNuNELnMPS4RdT
StreamColor (sdr/hlg, Apple Log slots in later) threads from format
selection to the wire: HLG restricts formats to x420 with BT.2020 HLG
capture, pins activeColorSpace, encodes HEVC Main10 with BT.2020/HLG
VUI tags, and adds "color":"hlg" to VIDEO_CONFIG (absent = SDR).
The toggle only appears on devices that encode Main10, forces HEVC
(H.264 hides while on), degrades to SDR when a combo lacks an HLG
format — never a black stream — and bumps bitrate 25% for the extra
depth. STATE advertises HEVC-only codecs plus "hdr":true while
active; SDR snapshots and paths are byte-identical to before.

Release-Skip: true

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015dWUcqAkNNuNELnMPS4RdT
Software HEVC Main10 decode now reaches OBS: yuv420p10 maps to I010,
the frame's transfer function rides along as trc (never set before —
even hardware P010 rendered with the SDR transfer), and colour params
come from the format-aware variant so 10-bit ranges are right. The
GPU-pipeline beta learns 10-bit CPU upload (P010 as R16+RG16, I010 as
three R16 planes) with new HLG effect techniques that own the whole
chain — BT.2020 limited-range matrix, BT.2100 inverse OETF + reference
OOTF, BT.2087 primaries, no clamping — and a video_get_color_space
callback reporting the extended-range canvas; 10-bit hardware surfaces
are refused by the zero-copy mappers (they'd import as garbage or
black) and take the CPU path until stage 2. gpu_frame_map_result now
carries a pixel-format enum instead of an rgba bool, ready for
zero-copy 10-bit. SDR behaviour is bit-identical throughout.

Release-Bump: minor
Release-Beta: true

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015dWUcqAkNNuNELnMPS4RdT
@MyNamesEMurray
MyNamesEMurray enabled auto-merge July 25, 2026 08:48
@MyNamesEMurray
MyNamesEMurray merged commit 0689abc into main Jul 25, 2026
6 checks passed
@MyNamesEMurray
MyNamesEMurray deleted the claude/init-lklchz branch July 25, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants