Repository navigation
fix(mux): settle catalog estimates before they churn - #7161
Conversation
Quest-Claim: bb79474b6f256afd
Hang republishes a measured jitter or delay rise only once it reaches the next whole frame duration above the published value: 1/framerate when the config has one, else the shortest timestamp advance measured. MSF waits until every unhinted video and audio track has closed a group after a second of media (and measured its framerate window, for unhinted video), declares its estimates once, freezes them, and skips writing a catalog identical to the last one. A finished track stops holding MSF back. Closes #7067 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MSF publishes once every unhinted track has closed its first group and carried a second of media, with no extra wait for the video framerate window. Unhinted video now declares no framerate in MSF. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 11 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: bed9baf
P2 — Release an existing MSF hold when set supplies all estimates (rs/moq-mux/src/catalog/tracks.rs:694-697). The public container::Producer::set can replace an initially unhinted config with a fully hinted one before its measurement window closes. This sets self.settled = true but leaves its previously inserted key in State.msf.unsettled. Subsequent estimates no longer call settle, and even finish cannot clear it because Rendition::settle returns early for an already-settled rendition. While that enabled track stays listed, the entire MSF catalog remains withheld indefinitely. Clear the catalog-side hold when set transitions to settled, before the corresponding publish; add a regression for unhinted set → fully hinted set → continued media/finish.
Direction: keeping Hang's live estimates separate from MSF's first-declaration values and deduplicating serialized MSF output is sound, without adding configuration. The two copies of settlement state need to transition together.
Verification: static review of the changed estimator/catalog code and public container lifecycle, with an independent review of the gate path. No tests or playback checks run.
Replacing an unhinted config with one hinting every estimated field marked the rendition settled but left the catalog waiting on it, withholding MSF for as long as the track stayed listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Fixed the P2 from the automated review in 945ceae. (Written by Claude Opus 5.5) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 945ceaedab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 945ceae
The prior P2 MSF settlement-hold finding is fixed: set now synchronizes the catalog-side hold with the rendition's settled flag before committing, and the new regression covers an unhinted → fully hinted replacement publishing MSF immediately. No new actionable bugs found in this delta.
Direction: a small, appropriate fix that keeps the existing settlement model rather than adding another publication path.
Verification: static review of the single-commit delta from bed9baf and surrounding set/settle code. No tests or playback checks run.
MSF held its catalog back until every unhinted track was measured, which deadlocks demand-driven publishers: they produce no media until a viewer subscribes, and an MSF viewer finds their tracks only through MSF. MSF now declares only the estimates a publisher hinted and publishes at once; hang keeps its measured estimates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 980af56
No new actionable bugs found in the hints-only MSF redesign. Removing the measurement gate addresses the independent P1 demand-driven discovery deadlock; the earlier P2 stranded settlement hold is also no longer applicable because settlement tracking is gone. The new undemanded-track regression checks immediate discovery without estimates, while hinted fields remain frozen after first declaration.
Direction: publishing the track list immediately and keeping live measurements in Hang is simpler than coordinating settlement with demand. Requiring explicit MSF hints is a meaningful compatibility choice, now documented in the bindings and PR impact. Hint registration/removal and supply_bitrate retain that separation.
Verification: static review of the substantive catalog delta since 945ceae, surrounding publication paths, tests and binding documentation, accounting for the main merge separately. No tests or playback checks run.
|
Landing this head (980af56) on the maintainer's approval.
(Written by Claude Opus 5.5) |
Closes #7067
Implements quest/m1/catalog-estimates.md and deletes it.
Summary
Hang quantizes jitter and delay rises.
Rendition::estimatenow takes aReading: theEstimateplus a frame period. A measuredjitterordelayrise republishes only once it reaches the next whole frame duration above the published value. The step is1/frameratewhen the config has one, otherwise the shortest timestamp advance the estimator has seen. The value published is the one measured at that moment. The once-a-second throttle still applies on top, and until a period is known it is the only pacing. Measurement itself is unchanged.MSF declares only hinted estimates, freezes them, and deduplicates. A new
Msfstate, kept under the catalog lock:bitrate,framerate,jitteranddelaya publisher hinted, meaning the fields a rendition's config carried atsetor thatsupply_bitratesupplied. A field with no hint stays absent from MSF, whatever hang measures. MSF publishes alongside hang from the start and never waits for a track to be measured, so demand-driven publishers can't deadlock it (see Decisions).moq_json.Hang's catalog keeps its measured estimates.
Impact
VideoHint, or through the moq-c and moq-ffi video hints. Audio through moq-c and moq-ffi has no hint, so its MSF tracks carry no bitrate. Hang viewers are unaffected.Tests
New tests in
catalog/producer.rs:a_creeping_delay_republishes_once_per_frame: delay creeping in 1 ms steps against a 10 ms period publishes 10, 20 and 30 only.a_framerate_sets_the_delay_stepidentical_msf_content_publishes_oncean_unhinted_track_declares_msf_at_once: an unhinted video track with no media written, as a demand-driven publisher's is, appears in MSF right away with no bitrate, framerate, jitter or delay. They stay absent after hang measures 25 fps and a bitrate.a_hinted_track_carries_its_hints: hinted bitrate and framerate appear in MSF. A later measured delay and asupply_bitratechange reach hang but leave MSF as first declared.Local checks (latest head):
cargo fmt --check,cargo clippy --workspace --all-targets --all-features -D warnings: clean.cargo test -p moq-mux -p moq-audio -p moq-ffi -p moq-c --all-features: passes after mergingmain.cargo test --workspace --all-features --no-fail-fast(before the merge): passes exceptmoq-clock'spaused_runtimes_own_their_anchors, which fails on main too, andkio'seviction_frees_whatever_readers_do, which fails only in workspace runs.Decisions
set.Choices made without asking
RenditionConfiginext, through itsset_estimate. A rendition that doesn't measure (text, or a config written throughmutate) goes to MSF as the catalog has it. An edit made throughmodifyto a measuring rendition's estimate fields reaches hang but not MSF.supply_bitratedoes.flush_if_readynow emits under the state lock, asGuard::publishalready did, because the MSF state lives there.Suggested follow-ups
Timestamp::now(), so a publish from a different clock context fails withTimestampMismatchif it lands earlier than the previous group. The moq-ffi paused-time test hit this with an extra finish-time hang publish, which an earlier head removed. Stamping withmax(now, last)would be more robust.Two earlier follow-ups no longer apply. "Successor tracks hold MSF back" went with the hold. "Extension sections still churn MSF" is gone too, because hints now apply to ext renditions.
(Written by Claude Opus 5.5)
🤖 Generated with Claude Code