feat(sdes): make the offer's video codec preference order settable - #226
Merged
Merged
Conversation
A correction first, because the docs in this repo have said otherwise and the correction is most of the value here. The SDES offer does not "express no preference" between H264 and H265. RFC 3264 section 5.1 makes the m=video payload-type list a preference list, most-preferred first, and the offer built in sdes_open.py has always carried "96 97" - H264 first. What is true is weaker and more useful: nothing ever chose that order. The line arrived verbatim when the SDES open path was split out of client.py and has never been varied since. That reframes the lever rather than strengthening it. On an A001064 the camera answers H264 most sessions and H265 occasionally for an identical request, which read against the offer is a camera that honours our stated first choice most of the time and disregards it some of the time. So expressing a preference is a weaker candidate than pinning was, not a stronger one. It is still worth being able to set, because the efficient profile - hevc 2560x1440 at about 1.1 Mbps against h264 1280x720 at 2.5-4.0 Mbps - has only ever appeared when both codecs are on the wire. AIDOT_SDES_VIDEO_PT=97 narrows the offer to H265 and returns no video at all, 3 of 3 rounds: narrowing removes the option rather than selecting it. Reordering is the only untried lever that leaves both codecs offered, so the camera can still fall back to H264. AIDOT_SDES_VIDEO_PT_ORDER takes a comma- or space-separated payload-type list. Whatever is named leads, in the order named, and every advertised codec not named is appended in the default order - so it can express a preference and can never narrow the offer. The result is always a permutation of the full advertised set, whatever the value, because an m=video line with no payload type leaves the camera nothing to send and that is the one outcome worse than an unpinned choice. Ordering runs before the existing pin, so with both set the pin wins. The default is deliberately unchanged and unset is byte-identical to 1.0.0b1. This path is shared by every SDES camera, the CHANGELOG records fleet-wide blackouts from changes to shared paths, and whether the camera acts on m-line order is exactly the untested question - so it ships off, with a status line that reports the order whenever it differs from the shipped one. A run that cannot show the knob reached the SDP cannot tell an effect from a coincidence, which is how the first attempt at the pin read as a confirmed result for two sessions before the missing receipt caught it. The m-line and the rtpmap/fmtp block now come from one helper, so they cannot drift apart: an m-line naming a payload type whose rtpmap was left behind is an offer the camera cannot act on. The tests assert the payload-type order in the generated m-line and codec block via the same helper the offer builder calls, and an AST guard checks the builder really calls it - the offer is assembled inside a several-hundred-line async method that cannot be invoked standalone, so a test against a copy of the template would pass with this change reverted. Both were verified by reverting the production edit and by flipping the default order, and each mutation fails the suite.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
AIDOT_SDES_VIDEO_PT_ORDER- opt-in, off by default, inert unless set - makesthe video codec preference order in the SDES offer settable per run. It ships
off, with the experiment that would confirm or kill it written out below.
First, a correction to what this repo says is established
docs/ROAD-TO-1.0.md, the CHANGELOG, and the ledger all say our offer"advertises both video codecs and expresses no preference". Checked against the
code, that is not what the SDP says.
RFC 3264 section 5.1 makes the
m=videopayload-type list a preference list,most-preferred first. The offer built in
sdes_open.pyhas always carried:H264 first. It states a preference, and always has.
What is true is weaker and more useful: nothing ever chose that order.
git log -Lon the line shows it arrived verbatim inabe6d6a, the commit thatextracted the SDES open path out of
client.py, and it has never been variedsince. Incidental, not deliberate.
Why the correction matters more than the knob
It changes the prior. The A001064 answers H264 most sessions and H265
occasionally for an identical request. Read against an offer that already says
"H264 first", that is a camera which honours our stated preference most of the
time and disregards it some of the time. So reordering is a weaker candidate
than pinning was, not a stronger one - the camera has already demonstrated it
will ignore first-listed.
I am not going to let the PR read as if a preference vacuum was established and
this fills it. It did not, and this does not.
Why it is still worth being able to set
The efficient profile - hevc 2560x1440 at ~1.1 Mbps against h264 1280x720 at
2.5-4.0 Mbps - has only ever appeared when both codecs are on the wire.
AIDOT_SDES_VIDEO_PT=97narrows the offer to H265 and returns no video at all,3 of 3 rounds: narrowing removes the option rather than selecting it.
Reordering is the only untried lever that leaves both codecs offered, so the
camera can still fall back to H264. That is the whole argument, and it is enough
for an off-by-default knob.
What changed
m=videopayload-type list and itsrtpmap/fmtpblock now comefrom one helper, so they cannot drift apart: an m-line naming a payload type
whose rtpmap was left behind is an offer the camera cannot act on.
AIDOT_SDES_VIDEO_PT_ORDERtakes a comma- or space-separated payload-typelist (
97,96, or just97). Whatever is named leads, in the order named;every advertised codec not named is appended in the default order.
is always a permutation of the full advertised set, for any value including
garbage - a video m-line with no payload type at all leaves the camera nothing
to send, which is the one outcome worse than an unpinned choice. Narrowing
already has its own variable, and the one time it was measured it cost the
picture.
not assumed.
SDES: offer video codec order=97 96, prints whenever the orderdiffers from the shipped one.
AIDOT_SDES_VIDEO_PT, which wasdocumented only in the CHANGELOG.
The default is not changed. Unset, the offer is byte-identical to 1.0.0b1.
This path is shared by every SDES camera, the CHANGELOG records fleet-wide
blackouts from changes to shared paths, and the hypothesis is untested on
hardware - a release is validating right now and this must not touch it.
Tests
The offer is assembled inside a several-hundred-line async method that cannot be
invoked standalone, so a test against a private copy of the template would pass
with the production change reverted. Instead:
actual payload-type order in the generated m-line and codec block.
replaced, character for character - the risk in this refactor is a dropped or
doubled
\r\nat the seams, not the codec names.permutation of
(96, 97), never narrowed, never empty, every m-line payloadtype carrying its own rtpmap.
list and takes its codec block from the helper, so a hard-coded
96 97cannotcome back with every other test still green.
travels compressed in
wPayload.offer.sdp, which is what newer firmwareparses. It exercises
protocol._compress_sdp_for_camera; the SDES path runs aclosure of the same shape (
_compress_sdp_req, defined inside the open methodand not importable), whose video branch has the same two properties asserted
here. That closure is its untested twin and the test says so.
Both guards were verified by mutation, not by assumption:
test_the_offer_builder_takes_its_video_codec_list_from_the_helperfails_SDES_OFFER_VIDEO_PT_ORDERto(97, 96)-> 3 tests fail, including the byte-identity oneuvx ruff check aidot_cameras/ tests/clean.pytest tests/ -q --ignore=tests/e2e:1077 passed, 5 skipped. The e2e tier hangs on this machine after the first test -
confirmed pre-existing: a clean
origin/mainworktree hangs at the samepoint, so it is environmental and not this change. CI runs that tier.
The experiment that would confirm or kill this
Do not merge. The knob is inert until someone sets it, and what it is for is the
run above.