Repository navigation
Interlaced live H.264 with unknown demuxer field_order stays on native decode (AVPlayer/VideoToolbox), produces persistent green colour cast #150
Description
What happened?
Some interlaced live H.264 channels show a persistent green colour cast from the first frame, sustained throughout playback — not a transient flash, not blocky/glitchy corruption, and not explained by bad colour VUI (both the affected and a clean comparison channel report identical, correct BT.709 limited-range tagging).
Root cause, confirmed by comparing SPS across an affected channel and a clean one: the affected channel's SPS has frame_mbs_only_flag=0 — it's genuinely interlaced at the bitstream level. Per #107, interlaced content is meant to route to software decode, since AVPlayer/VideoToolbox on tvOS doesn't deinterlace. That routing rule is keyed off the demuxer's own field_order probe (TT/BB/TB/BT). On this stream, the demuxer's field_order came back UNKNOWN rather than a concrete value, even though the SPS unambiguously marks the content as interlaced. Because the rule only checks field_order and not the SPS's own frame_mbs_only_flag, the channel stayed on native/VideoToolbox decode, and the resulting output has the incorrect colour cast.
I expected interlaced content to route to software decode per #107 regardless of whether the demuxer's separate field-order probe resolves; instead, an inconclusive field_order silently defeats that routing decision even when the SPS itself is decisive.
Steps to reproduce
- Tune a live H.264 channel whose source is interlaced at the SPS level (frame_mbs_only_flag=0) but where the demuxer's own field-order detection returns UNKNOWN rather than TT/BB/TB/BT.
- Observe the routing dispatch log: dispatch: codec=27 → native with fieldOrder=0 (UNKNOWN).
- Compare against a genuinely progressive channel on the same provider: same dispatch path (native), correctly so, with fieldOrder=1 (PROGRESSIVE).
- On the interlaced-but-misrouted channel, observe a persistent green cast on screen from the first frame, sustained throughout — confirmed via screen recording, and confirmed not present when the same TV/HDMI setup plays other content via a different app (rules out display/HDMI).
AetherEngine version or commit SHA
5.8.5
Host app
Custom / my own integration
Platform
tvOS
OS version
tvOS 26.6 (beta)
Device / chip
Apple TV 4K (A15)
Playback path
Native AVPlayer
Source media (for playback bugs)
MPEG-TS live source (UK terrestrial simulcast via Xtream-style IPTV provider), H.264 Main profile, 1920x1080, both channels below from the same provider for direct comparison:
Error codes / log lines
dispatch: codec=27 → native
fieldOrder=0 (UNKNOWN)
No decode errors, no SPS/PPS reference errors, no parse failures — the stream decodes "successfully" in the sense that nothing errors, but the output is visually wrong. This is a routing-decision bug, not a decode-error bug, which is why it produces no error-level log lines at all.
Anything else
We confirmed the colour-VUI hypothesis first (thinking this might be a tagging mismatch) and ruled it out — both channels report identical, correct BT.709 tags. The only meaningful delta between the two channels is frame_mbs_only_flag.
We also confirmed there's no public LoadOptions control to force software decode as a host-side workaround — only AetherEngine.setForceSoftwarePathForTesting / aetherctl live --sw, which are explicitly test-only, not intended for app use. So there's no way for us to route around this from MediaHub's side; it needs to be fixed at the routing-decision layer.
Proposed fix shape: when field_order comes back UNKNOWN from the demuxer probe, fall back to checking frame_mbs_only_flag (and mb_adaptive_frame_field_flag, if relevant to the coding structure) directly from the parsed SPS before defaulting to native decode. The SPS parsing to get this value already exists elsewhere in the engine (used for the join-gate/rotation work in #130-adjacent fixes), so this may just be a matter of consulting it as a fallback signal in the routing decision rather than only relying on the demuxer's separate field-order detection.
Happy to test a build against this specific channel — it's reliably reproducible on our end.
Activity
Merge fix/ae150-sps-interlaced-routing-fallback: SPS frame_mbs_only f…
docs: changelog entry for 5.9.6 (#150 SPS frame_mbs_only routing fall…
superuser404notfound commentedon Jul 19, 2026
Fixed in 5.9.6 (PR #155). Your diagnosis was spot on, thanks for the SPS-level comparison between the two channels; it pointed straight at the root cause.
What changed: the #107 routing rule keyed only off the demuxer's
field_orderprobe, soUNKNOWNsilently defeated it even when the SPS was decisive. The routing decision now falls back to parsing the SPS from codecpar extradata (Annex-B and avcC layouts) when the probe is inconclusive, and treatsframe_mbs_only_flag=0as interlaced. Exactly the fix shape you proposed.Notes on the behavior:
PROGRESSIVEprobe result still wins over the SPS flag, since the probe analyzed actual frames whileframe_mbs_only_flag=0only says the stream may code interlaced pictures.AV_FRAME_FLAG_INTERLACEDin the slice headers, so progressive frames pass through untouched.fieldOrder=UNKNOWN but SPS frame_mbs_only_flag=0; treating as interlaced for routing (#150)right before the dispatch line, which should now readdispatch: codec=27 -> softwareon the affected channel.Since you offered to test against the specific channel: a retest on 5.9.6 would be much appreciated. If the green cast persists on the software path, please reopen with the new dispatch log lines.
fix: fall back to SPS frame_mbs_only_flag when demuxer field_order is…
fix(swhost): resolve live-TS audio the probe left with empty codecpar (…
Exclude the in-path VT decoder for interlaced H.264 (superuser404notf…