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
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:
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user