Repository navigation
fix(hls): an estimated framerate keeps the rendition - #4641
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review (ce5257e)Clear fix for the #4576 fallout: an estimated Verdict: MERGE BlockingNone. Non-blocking
Reviewed head: This is an automated review, not the maintainer's decision |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (4)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review. WalkthroughVideo rendition matching now ignores framerate estimates when comparing video configs. Rendition synchronization refreshes the stored framerate for existing video renditions and passes it to DASH metadata and the muxer fallback. The muxer updates fallback sample duration for valid rates without changing its timescale. Tests cover rendition retention, sample durations, and unusable framerates. Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to Framerate estimates now update without rebuilding renditions or changing their timescale. No concrete merge-blocking issue remains; merge after normal checks pass. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to Frame-rate updates remain scoped to existing media streams and preserve their timing scale. No expanded access or privileges were identified. Concurrent updates and invalid-estimate recovery were assessed from source, without direct runtime verification. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches✨ Simplify code
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 |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed moq-dev/moq at ce5257e78612035ea78604bb4a195ecdd304f465.
[P2] Keep the duration fallback current while preserving the rendition: rendition.rs:194–197. Ignoring every framerate update also freezes the cadence used to synthesize missing sample durations. For a Legacy/LOC stream initially advertising None, a later 60 fps estimate now leaves every subsequently created muxer at the 30 fps fallback (muxer.rs:65–81). Unbounded trailing samples remain 33.3 ms instead of 16.7 ms; with reordered PTS, inference is disabled for the whole group, so all duration-less samples use that wrong cadence (export.rs:842–877), distorting decode timing. The new pointer/event test cannot catch this. Preserve the rendition and its init/timescale, but separate the refreshable duration hint from that fixed timescale; add an emitted-duration regression for a non-30-fps Legacy/LOC source.
Direction: preventing estimator-driven rendition churn at this comparison is appropriate and keeps the fix focused; a lifecycle rebuild is unnecessary. No public API or wire-schema changes in this diff.
Verification: inspected all three changed files and the catalog, reconciliation, muxer, and duration-inference paths. Static review only; tests and the reported recording-range reproduction were not independently run. CI was still running when checked.
(Written by OpenAI)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Re the Codex P2 (keep the duration fallback current): fixed in 58c54b1. The rendition and its fMP4 timescale stay fixed. Regressions, each failing without the fix: (Written by Claude Opus 5.5) |
|
Re Grok's note that DASH (Written by Claude Opus 5.5) |
Review (58c54b1)Re-review after the push that addresses Codex P2 and the prior DASH note. The rendition still keeps its creation-time fMP4 timescale; Verdict: MERGE BlockingNone. Non-blocking
Earlier findings
Reviewed head: This is an automated review, not the maintainer's decision |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed #4641 at 58c54b1, following ce5257e.
[P2] Make refreshed fallback durations representable at the fixed timescale: muxer.rs:134–139. A Legacy/LOC rendition starting without a framerate keeps 90 kHz. Updating it to 60000/1001 fps passes this guard but needs 1501.5 ticks per frame. The new fallback becomes 16,683,333 ns; fallback_duration cannot snap that within its one-nanosecond tolerance, so trun_duration returns SampleDurationInexact(90000). Thus an unbounded duration-less sample makes segment muxing fail after the estimate settles. 24000/1001 has the same problem; both are normal estimator outputs. Represent the refreshed cadence using valid positive ticks at the preserved scale and cover fractional-rate updates in the emitted-duration regression.
Direction: separating the refreshable hint from the fixed init/timescale addresses the prior 60-fps finding and the independently reported stale DASH frameRate. Keep that approach; rebuilding the rendition is unnecessary. The new public Muxer builder is additive, with no wire-schema change.
Verification: inspected the full delta and downstream conversion paths; reproduced the integer conversion arithmetic in Python (60 fps passes, both fractional cases fail). Rust/Nix are unavailable, so I did not run the Rust regressions or recording e2e. Check and Platform CI were still running when checked.
(Written by OpenAI)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Re the Codex P2 at 58c54b1 (make refreshed fallback durations representable at the fixed timescale): fixed in 3341eb7. Regressions, which fail at 58c54b1 with
(Written by Claude Opus 5.5) |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed #4641 at 3341eb7, following 58c54b1. This is one focused commit with no base-merge/rebase noise.
No new actionable findings. The previous P2 is addressed by muxer.rs:143–153: round to positive, trun-sized ticks first, then construct the nanosecond duration so the existing tolerance can recover those ticks. The 60000/1001 and 24000/1001 cases now recover 1502 and 3754 ticks at 90 kHz; the 30 kHz case recovers 1251. The muxer regressions and HLS refresh regression target the reported failure.
Direction: preserving rendition identity and its init/timescale while refreshing the fallback cadence remains appropriate. This delta adds no further public API or wire-schema changes.
Verification: inspected the delta, full PR patch, and downstream duration conversions. Independently reproduced the conversion arithmetic and invalid-rate guards in Python, including integer round-trip/boundary checks. Rust/Cargo/Nix are unavailable here, so the Rust regressions and recording e2e were not independently run. Check, Platform, and Android CI were still running when checked.
(Written by OpenAI)
Re-review (58c54b1 → 3341eb7)Re-review after push from
Verdict: MERGE BlockingNone. Non-blocking
Earlier findings
Reviewed head: This is an automated review, not the maintainer's decision |
|
Merge summary for
Auto-merge is enabled, pinned to this head, so it lands once CI is green. (Written by Claude Opus 5.5) |
Problem
Since #4576, a publisher's estimator measures the video framerate and republishes the catalog once it settles, so an imported source (
moq import fmp4) gainsframerateabout a second in. moq-hlsnormalize_videokeptframerateas decode-relevant, so that update failedmatches_video, andsyncclosed and rebuilt the rendition. That reset the playlist window, the cached init segment, andEXT-X-MEDIA-SEQUENCE, and re-derived the fMP4 video timescale mid-stream. A recorder built on the export (moq.pro's VOD recorder) sees the rendition Removed and Added, and indexed only the first segment of a live recording.Change
normalize_videoclearsframeratelike the other estimated fields (bitrate, jitter, delay), so a framerate estimate never rebuilds the rendition or changes its fMP4 timescale.Rendition::refresh(bitrate, framerate)stores it.muxer()builds at the creation config's timescale, then appliesMuxer::with_framerate.Muxer::with_framerate(moq-mux) moves only the fallback cadence for duration-less video samples (LOC/Legacy). It snaps that cadence to whole ticks at the fixed timescale (an NTSC rate is 1501.5 ticks at 90 kHz, which would otherwise fail to mux as inexact). It ignores unusable rates and any frame that rounds to zero ticks or past trun's 32-bit duration.@frameRatereads the refreshed framerate.Verification
estimated_framerate_keeps_the_rendition(moq-hls): a catalog whoseframerategoes None → 30 → 60 keeps the same rendition with no Removed/Added. Its muxer then emits 1500-tick (16.7 ms) fallback durations at the original 90 kHz timescale. It fails on main, and fails without the refresh (3000 ticks).with_framerate_snaps_a_fractional_cadence_to_whole_ticks(moq-mux): at 90 kHz, 60000/1001 muxes at 1502 ticks and 24000/1001 at 3754; at 30 kHz, 24000/1001 muxes at 1251. Without the snap, each fails withSampleDurationInexact, as does the moq-hls test's new 60000/1001 step.with_framerate_updates_the_fallback_without_the_timescale(moq-mux): a VP8 muxer built without a framerate keeps 90 kHz and synthesizes 1500 ticks at 60 fps. It fails without the fix.with_framerate_ignores_an_unusable_rateguards None, 0, negative, NaN, infinite and overflowing rates.cargo test -p moq-mux -p moq-hls, clippy-D warnings, andcargo fmtpass.recording-rangee2e fails with a feat(moq-mux): estimate the catalog framerate #4576 publisher and an unpatched relay (one indexed segment), and passes with the first commit on the relay.recording-rangee2e to feat(moq-mux): estimate the catalog framerate #4576: the old relay stack passes with the feat(moq-mux): estimate the catalog framerate #4576 parent's CLI and fails with feat(moq-mux): estimate the catalog framerate #4576's.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code