style: rustfmt the freeze-until-reanchor client wiring
ci / web (push) Successful in 57s
ci / docs-site (push) Successful in 1m7s
ci / bench (push) Successful in 5m11s
decky / build-publish (push) Successful in 28s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 40s
deb / build-publish (push) Successful in 11m37s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
arch / build-publish (push) Successful in 15m30s
apple / swift (push) Successful in 4m19s
android / android (push) Successful in 16m52s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8m34s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10m14s
windows-host / package (push) Successful in 13m57s
flatpak / build-publish (push) Successful in 5m48s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m46s
ci / rust (push) Successful in 22m54s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m7s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 5m1s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m27s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m1s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 5m30s
release / apple (push) Successful in 21m2s
docker / deploy-docs (push) Successful in 21s
apple / screenshots (push) Successful in 19m51s

cargo fmt --all --check flagged the reanchor gate wiring (decode.rs / session.rs /
abi.rs / reanchor.rs): wrapped signatures + comparisons, and two multi-line comments
that followed a trailing-comment line were restructured to their own lines so
rustfmt keeps them at normal indentation instead of deep-aligning them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-13 07:36:35 +02:00
parent 644c035a34
commit cdb43f00fe
4 changed files with 36 additions and 13 deletions
+4 -2
View File
@@ -1480,13 +1480,15 @@ fn drain(
loop {
match codec.dequeue_output_buffer(wait) {
Ok(DequeuedOutputBufferInfoResult::Buffer(buf)) => {
wait = Duration::ZERO; // only the first dequeue may block
// Only the first dequeue may block; later ones poll (wait == ZERO).
wait = Duration::ZERO;
// Fold every dequeued frame through the gate in pts (== decode) order — even the ones
// the newest-wins policy discards — so the two-mark re-anchor count stays correct; the
// verdict of the newest (last folded) buffer decides whether it reaches glass.
let pts_us = buf.info().presentation_time_us().max(0) as u64;
let flags = take_flags(recovery_flags, pts_us);
held_present = gate.on_decoded(flags, false, Instant::now()) == GateVerdict::Present;
held_present =
gate.on_decoded(flags, false, Instant::now()) == GateVerdict::Present;
let meta = if stats.enabled() {
// The dequeue IS the sync loop's decoded-availability instant.
let decoded_ns = now_realtime_ns();
+7 -4
View File
@@ -402,9 +402,9 @@ fn pump(
// takes `image.is_keyframe()` as the ffmpeg keyframe belt, applies the two-mark
// rule + the mark-patience backstop, clears the no-output streak, and returns
// whether to present this frame or withhold it as a post-loss concealment.
let present = gate
.on_decoded(frame.flags, image.is_keyframe(), Instant::now())
== GateVerdict::Present;
let present =
gate.on_decoded(frame.flags, image.is_keyframe(), Instant::now())
== GateVerdict::Present;
total_frames += 1;
dec_path = match &image {
DecodedImage::Cpu(_) => "software",
@@ -577,7 +577,10 @@ fn pump(
{
last_kf_req = Some(now);
let _ = connector.request_keyframe();
tracing::debug!(dropped, "requested keyframe (loss recovery / overdue re-anchor)");
tracing::debug!(
dropped,
"requested keyframe (loss recovery / overdue re-anchor)"
);
}
if window_start.elapsed() >= Duration::from_secs(1) {
+2 -1
View File
@@ -2685,7 +2685,8 @@ pub unsafe extern "C" fn punktfunk_reanchor_gate_on_decoded(
Some(g) => g,
None => return PunktfunkStatus::NullPointer,
};
let present = g.on_decoded(flags, decoder_keyframe, std::time::Instant::now()) == GateVerdict::Present;
let present = g.on_decoded(flags, decoder_keyframe, std::time::Instant::now())
== GateVerdict::Present;
if !out_present.is_null() {
unsafe { *out_present = present };
}
+23 -6
View File
@@ -82,7 +82,12 @@ pub fn index_gap(expected: u32, got: u32) -> Option<u32> {
/// independent of the pump's channel/decoder plumbing — the first wave boundary after a loss is only
/// partially healed, so a single mark must NOT lift. An anchor (or IDR) is a *whole* re-anchor and
/// lifts immediately.
fn reanchor_after_frame(is_keyframe: bool, has_anchor: bool, has_mark: bool, marks: u32) -> (bool, u32) {
fn reanchor_after_frame(
is_keyframe: bool,
has_anchor: bool,
has_mark: bool,
marks: u32,
) -> (bool, u32) {
let marks = if has_mark {
marks.saturating_add(1)
} else {
@@ -171,7 +176,12 @@ impl ReanchorGate {
///
/// [`USER_FLAG_RECOVERY_ANCHOR`]: crate::packet::USER_FLAG_RECOVERY_ANCHOR
/// [`USER_FLAG_RECOVERY_POINT`]: crate::packet::USER_FLAG_RECOVERY_POINT
pub fn on_decoded(&mut self, wire_flags: u32, decoder_keyframe: bool, now: Instant) -> GateVerdict {
pub fn on_decoded(
&mut self,
wire_flags: u32,
decoder_keyframe: bool,
now: Instant,
) -> GateVerdict {
self.no_output_streak = 0;
let is_keyframe = decoder_keyframe || (wire_flags & FLAG_SOF as u32 != 0);
let has_anchor = wire_flags & USER_FLAG_RECOVERY_ANCHOR != 0;
@@ -259,7 +269,10 @@ mod tests {
// The first wave boundary after a loss is only half-healed — one mark must hold the freeze.
assert_eq!(REANCHOR_MARKS_TO_LIFT, 2);
assert_eq!(lift_at(&[(false, true)]), None);
assert_eq!(lift_at(&[(false, false), (false, true), (false, false)]), None);
assert_eq!(
lift_at(&[(false, false), (false, true), (false, false)]),
None
);
}
#[test]
@@ -408,7 +421,10 @@ mod tests {
assert!(!g.poll(5, now), "no climb → no ask"); // baseline
assert!(g.poll(6, now), "a climb asks for a keyframe");
assert!(g.is_holding(), "and arms the freeze");
assert!(!g.poll(6, now), "same value → no repeat ask from the drop path");
assert!(
!g.poll(6, now),
"same value → no repeat ask from the drop path"
);
}
#[test]
@@ -448,8 +464,9 @@ mod tests {
g.arm(start);
// A mark past the original freeze deadline pushes it out by RECOVERY_MARK_PATIENCE.
let t = start + REANCHOR_FREEZE_MAX + Duration::from_millis(10);
assert_eq!(g.on_decoded(POINT, false, t), GateVerdict::Hold); // mark #1, deadline pushed
// At a time that WOULD have been overdue on the original deadline, poll does not re-ask.
// mark #1 pushes the deadline out; at a time that WOULD have been overdue on the ORIGINAL
// deadline, poll does not re-ask.
assert_eq!(g.on_decoded(POINT, false, t), GateVerdict::Hold);
assert!(!g.poll(0, t + Duration::from_millis(1)));
assert!(g.is_holding());
}