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 {
|
loop {
|
||||||
match codec.dequeue_output_buffer(wait) {
|
match codec.dequeue_output_buffer(wait) {
|
||||||
Ok(DequeuedOutputBufferInfoResult::Buffer(buf)) => {
|
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
|
// 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
|
// 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.
|
// 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 pts_us = buf.info().presentation_time_us().max(0) as u64;
|
||||||
let flags = take_flags(recovery_flags, pts_us);
|
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() {
|
let meta = if stats.enabled() {
|
||||||
// The dequeue IS the sync loop's decoded-availability instant.
|
// The dequeue IS the sync loop's decoded-availability instant.
|
||||||
let decoded_ns = now_realtime_ns();
|
let decoded_ns = now_realtime_ns();
|
||||||
|
|||||||
@@ -402,8 +402,8 @@ fn pump(
|
|||||||
// takes `image.is_keyframe()` as the ffmpeg keyframe belt, applies the two-mark
|
// 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
|
// 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.
|
// whether to present this frame or withhold it as a post-loss concealment.
|
||||||
let present = gate
|
let present =
|
||||||
.on_decoded(frame.flags, image.is_keyframe(), Instant::now())
|
gate.on_decoded(frame.flags, image.is_keyframe(), Instant::now())
|
||||||
== GateVerdict::Present;
|
== GateVerdict::Present;
|
||||||
total_frames += 1;
|
total_frames += 1;
|
||||||
dec_path = match &image {
|
dec_path = match &image {
|
||||||
@@ -577,7 +577,10 @@ fn pump(
|
|||||||
{
|
{
|
||||||
last_kf_req = Some(now);
|
last_kf_req = Some(now);
|
||||||
let _ = connector.request_keyframe();
|
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) {
|
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,
|
Some(g) => g,
|
||||||
None => return PunktfunkStatus::NullPointer,
|
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() {
|
if !out_present.is_null() {
|
||||||
unsafe { *out_present = present };
|
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
|
/// 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
|
/// partially healed, so a single mark must NOT lift. An anchor (or IDR) is a *whole* re-anchor and
|
||||||
/// lifts immediately.
|
/// 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 {
|
let marks = if has_mark {
|
||||||
marks.saturating_add(1)
|
marks.saturating_add(1)
|
||||||
} else {
|
} else {
|
||||||
@@ -171,7 +176,12 @@ impl ReanchorGate {
|
|||||||
///
|
///
|
||||||
/// [`USER_FLAG_RECOVERY_ANCHOR`]: crate::packet::USER_FLAG_RECOVERY_ANCHOR
|
/// [`USER_FLAG_RECOVERY_ANCHOR`]: crate::packet::USER_FLAG_RECOVERY_ANCHOR
|
||||||
/// [`USER_FLAG_RECOVERY_POINT`]: crate::packet::USER_FLAG_RECOVERY_POINT
|
/// [`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;
|
self.no_output_streak = 0;
|
||||||
let is_keyframe = decoder_keyframe || (wire_flags & FLAG_SOF as u32 != 0);
|
let is_keyframe = decoder_keyframe || (wire_flags & FLAG_SOF as u32 != 0);
|
||||||
let has_anchor = wire_flags & USER_FLAG_RECOVERY_ANCHOR != 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.
|
// 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!(REANCHOR_MARKS_TO_LIFT, 2);
|
||||||
assert_eq!(lift_at(&[(false, true)]), None);
|
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]
|
#[test]
|
||||||
@@ -408,7 +421,10 @@ mod tests {
|
|||||||
assert!(!g.poll(5, now), "no climb → no ask"); // baseline
|
assert!(!g.poll(5, now), "no climb → no ask"); // baseline
|
||||||
assert!(g.poll(6, now), "a climb asks for a keyframe");
|
assert!(g.poll(6, now), "a climb asks for a keyframe");
|
||||||
assert!(g.is_holding(), "and arms the freeze");
|
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]
|
#[test]
|
||||||
@@ -448,8 +464,9 @@ mod tests {
|
|||||||
g.arm(start);
|
g.arm(start);
|
||||||
// A mark past the original freeze deadline pushes it out by RECOVERY_MARK_PATIENCE.
|
// A mark past the original freeze deadline pushes it out by RECOVERY_MARK_PATIENCE.
|
||||||
let t = start + REANCHOR_FREEZE_MAX + Duration::from_millis(10);
|
let t = start + REANCHOR_FREEZE_MAX + Duration::from_millis(10);
|
||||||
assert_eq!(g.on_decoded(POINT, false, t), GateVerdict::Hold); // mark #1, deadline pushed
|
// mark #1 pushes the deadline out; at a time that WOULD have been overdue on the ORIGINAL
|
||||||
// At a time that WOULD have been overdue on the original deadline, poll does not re-ask.
|
// 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.poll(0, t + Duration::from_millis(1)));
|
||||||
assert!(g.is_holding());
|
assert!(g.is_holding());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user