Skip to content

The H.264 CODECS attribute states the profile the source declares - #439

Merged
superuser404notfound merged 1 commit into
mainfrom
fix/avc-codecs-string
Aug 27, 2026
Merged

superuser404notfound merged 1 commit into
mainfrom
fix/avc-codecs-string

Conversation

@superuser404notfound

Copy link
Copy Markdown
Owner

The master's CODECS entry was built as String(format: "avc1.%02X%02X%02X", codecpar.profile, 0, codecpar.level). AVCodecParameters.profile is not a bare profile_idc: libavcodec ORs the constraint flags into the high bits, so Constrained Baseline arrives as 66|AV_PROFILE_H264_CONSTRAINED = 578. %02X is a minimum width, so that printed as three digits and the attribute came out avc1.2420028, seven hex digits where RFC 6381 defines exactly six. Constrained High and the High 10 / 4:2:2 / 4:4:4 Intra profiles overflow the same way; Main and High carry no flags, which is why remuxes never showed it.

The hardcoded middle byte was the other half: profile_compatibility carries the constraint_set flags, and declaring zero contradicted the sample entry the muxer writes from the same extradata.

Both now come from the source in whatever form it carries them: the avcC states all three bytes, an MPEG-TS stream states them in the first three bytes of its SPS, and only a source with neither falls back to the codecpar fields, masked, with the two preserved flags mapped back into the compatibility byte. Same shape plainHEVCCodecs already had.

Verification

  • swift test: 2175 tests in 305 suites pass. 16 new tests in AVCCodecStringTests, written first and watched fail on the value (route.primaryCodecs -> "avc1.2420028"), including a shape assertion across all 13 H.264 profiles.
  • tvOS and iOS Simulator builds pass locally. visionOS SDK is not installed on this machine, so CI is the only coverage for it here.
  • End to end through aetherctl serve --native-subs, two binaries side by side on the same fixtures: High stayed avc1.640028 byte-identical, Constrained Baseline went avc1.2420028 -> avc1.42C028.

Scope

Only the manifest attribute changes. No segment or init byte moves, and only the master route is affected (a media-direct session declares no CODECS at all).

Not claimed: that the malformed string broke playback. macOS AVFoundation accepted both spellings in an A/B on identical media, so this is a spec violation whose consequence on tvOS is untested. The Annex-B/SPS branch is unit-tested against real AVCodecParameters, not end to end.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WbciAqCSxpaiUpTumrCuA9

…rce declares

The master's CODECS entry was built as
`String(format: "avc1.%02X%02X%02X", codecpar.profile, 0, codecpar.level)`, and
`AVCodecParameters.profile` is not a bare profile_idc: libavcodec ORs the
constraint flags into the high bits, so Constrained Baseline arrives as
`66|AV_PROFILE_H264_CONSTRAINED` = 578 and the Intra profiles as
`idc|AV_PROFILE_H264_INTRA`. `%02X` is a minimum width, not a maximum, so 578
printed as three digits and the attribute came out `avc1.2420028`: seven hex
digits where RFC 6381 defines exactly six. Measured on a Constrained Baseline
1080p23.976 fixture through `aetherctl serve --native-subs`. Constrained High and
High 10 / 4:2:2 / 4:4:4 Intra overflow the same way; Main and High carry no flags,
which is why remuxes never showed it.

The hardcoded middle byte was the second half: profile_compatibility carries the
constraint_set flags, and declaring zero for every source contradicted the sample
entry the muxer writes from the same extradata.

Both come from the source now, in the form it carries them: the avcC states all
three bytes (bytes 1..3), an MPEG-TS stream states them in the first three bytes
of its SPS, and only a source with neither falls back to the codecpar fields,
masked and with the two flags libavcodec preserved mapped back into the
compatibility byte. That is the same shape `plainHEVCCodecs` already had, and
deriving the attribute from the extradata the muxer stream-copies is what keeps
the manifest and the init from disagreeing by construction.

Scope: only the manifest attribute changes, no segment or init byte moves, and
only on the master route (a media-direct session declares no CODECS at all).
Sources whose profile carries no constraint flags are byte-identical before and
after, verified side by side on the same fixtures: High stayed `avc1.640028`
while Constrained Baseline went `avc1.2420028` -> `avc1.42C028`.

Not claimed: that the malformed string broke playback. macOS AVFoundation
accepted both spellings in an A/B on identical media, so this is a spec violation
whose consequence on tvOS is untested.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WbciAqCSxpaiUpTumrCuA9
@superuser404notfound
superuser404notfound merged commit 4948003 into main Aug 27, 2026
4 checks passed
@superuser404notfound
superuser404notfound deleted the fix/avc-codecs-string branch September 4, 2026 06:57
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.

1 participant