Skip to content

refactor: make the real-time policy layer testable (extract ABR + timeline normalizer) - #33

Merged
joeblau merged 1 commit into
mainfrom
feat/21-testable-realtime-policy
Jul 5, 2026
Merged

refactor: make the real-time policy layer testable (extract ABR + timeline normalizer)#33
joeblau merged 1 commit into
mainfrom
feat/21-testable-realtime-policy

Conversation

@joeblau

@joeblau joeblau commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Completes the StreamBroadcast-policy extraction for #21. The prior #20 work already moved the reconnect backoff, VideoFrameAdmission ratios, per-path bitrate ceiling, and the watchdog >-vs->= frozen-queue rule into StreamCore with tests; this lands the remaining two pieces, so the whole real-time policy layer is now unit-tested on CI instead of resting on manual device testing.

What moved

  • StreamCore/AdaptiveBitRateState.swift (new) — the adaptive-bitrate decision math as a pure Sendable/Equatable value type with mutating handlers returning an ABRDecision(shouldApply, severe): minimum floor, effectiveMaximum (path + thermal), insufficient-BW reduction (65% headroom / halve-on-zero), status stall-halving + healthy accounting, the 30-tick upward probe (step + cap), per-path interface seeding (lastGoodTarget / 0.6×), thermal-ceiling clamp, frameInterval, currentFrameRate. Copied character-for-character (truncation + floor-division preserved); frameInterval10/30 redefined bit-identically to HaishinKit's. BroadcastAdaptiveBitRateController becomes a thin actor that unwraps the HaishinKit event, delegates, and applies once (−241 net lines).
  • StreamCore/MediaTimelineNormalizer.swift (new) — MediaTimelineNormalizer + MediaTimelineKind moved out of the app target (pure CoreMedia, made public), with a pure static rebasedOffset() so the gap-accumulation math is testable with plain CMTime.

Tests

+25 StreamCore tests (19 ABR: floor, effectiveMaximum, reduction bytesOut>0/==0/floor, stall halving, probe steps + cap, stall/probe mutual-exclusivity, path-seed + interface switch + raised-probe-restart + thermal-cap-not-defeated, thermal clamp, capture-paused no-apply, reset, frameInterval severe/congestion/thermal, currentFrameRate; + 6 normalizer rebase/passthrough) — 124 total, all passing.

Behavior preservation

Adversarially reviewed vs main: no encoder-behavior change (state-fidelity + apply-equivalence dimensions found no functional divergence). The .status two-apply sites collapse into one ABRDecision — proven mutually exclusive per tick, so the single setVideoSettings is byte-exact. One log-only divergence the review caught (a stall apply logging "recovered") is fixed here. Both publishers' call sites are unchanged.

Full app builds against the iOS 27 SDK.

fixes #21

🤖 Generated with Claude Code

…eline normalizer)

Completes the StreamBroadcast-policy extraction for issue #21. The prior #20
work already moved the reconnect backoff, VideoFrameAdmission ratios,
per-path bitrate ceiling, and the watchdog >-vs->= frozen-queue rule into
StreamCore with tests; this lands the remaining two pieces so the whole
real-time policy layer is @testable-import-able (CI-run) instead of resting
on manual device testing.

- StreamCore/AdaptiveBitRateState.swift (NEW): the adaptive-bitrate decision
  math — minimum floor, effectiveMaximum (path + thermal), insufficient-BW
  reduction (65% headroom / halve-on-zero), status stall halving + healthy
  accounting, the 30-tick upward probe (step + cap), per-path interface
  seeding (lastGoodTarget / 0.6x), thermal-ceiling clamp, frameInterval, and
  currentFrameRate — as a pure Sendable value type with mutating handlers
  returning an ABRDecision. Copied character-for-character (truncation +
  floor-division preserved); frameInterval10/30 redefined bit-identically to
  HaishinKit's. BroadcastAdaptiveBitRateController becomes a thin actor that
  unwraps the HaishinKit event, delegates, and applies once (−241 net lines).
- StreamCore/MediaTimelineNormalizer.swift (NEW): MediaTimelineNormalizer +
  MediaTimelineKind moved out of the app target (pure CoreMedia, made public),
  with a pure static rebasedOffset() so the gap-accumulation math is testable
  with plain CMTime.

+25 StreamCore tests (19 ABR reduction/probe/floor/seed/thermal/frameInterval
cases + 6 normalizer rebase cases) — 124 total, all passing. Adversarially
reviewed for byte-for-byte behavior preservation: no encoder-behavior change
(a stall-vs-recovered log-line divergence the review caught is fixed here).
Full app builds against the iOS 27 SDK.

fixes #21

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@joeblau
joeblau merged commit d05f843 into main Jul 5, 2026
1 check passed
@joeblau
joeblau deleted the feat/21-testable-realtime-policy branch July 5, 2026 00:09
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.

M6 · Make the real-time layer testable (extract StreamBroadcast policy)

1 participant