fix(sync): coalesce stale upstream video backlog
This commit is contained in:
parent
38ead8c1e9
commit
65e6f84f8d
@ -4,7 +4,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.14.3"
|
version = "0.14.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.14.3"
|
version = "0.14.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bench = false
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.14.3"
|
version = "0.14.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
autobins = false
|
autobins = false
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,20 @@ fn upstream_stale_drop_budget() -> Duration {
|
|||||||
Duration::from_millis(drop_ms)
|
Duration::from_millis(drop_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(coverage))]
|
||||||
|
fn retain_freshest_video_packet(
|
||||||
|
pending: &mut std::collections::VecDeque<VideoPacket>,
|
||||||
|
) -> usize {
|
||||||
|
if pending.len() <= 1 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let newest = pending.pop_back().expect("non-empty pending video queue");
|
||||||
|
let dropped = pending.len();
|
||||||
|
pending.clear();
|
||||||
|
pending.push_back(newest);
|
||||||
|
dropped
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(coverage))]
|
#[cfg(not(coverage))]
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl Relay for Handler {
|
impl Relay for Handler {
|
||||||
@ -279,7 +293,18 @@ impl Relay for Handler {
|
|||||||
};
|
};
|
||||||
if let Some(next_packet) = next_packet {
|
if let Some(next_packet) = next_packet {
|
||||||
match next_packet.transpose()? {
|
match next_packet.transpose()? {
|
||||||
Some(pkt) => pending.push_back(pkt),
|
Some(pkt) => {
|
||||||
|
pending.push_back(pkt);
|
||||||
|
let coalesced = retain_freshest_video_packet(&mut pending);
|
||||||
|
if coalesced > 0 {
|
||||||
|
tracing::debug!(
|
||||||
|
rpc_id,
|
||||||
|
session_id,
|
||||||
|
dropped = coalesced,
|
||||||
|
"🎥 coalesced stale upstream video backlog down to the freshest frame"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
None => inbound_closed = true,
|
None => inbound_closed = true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,3 +429,33 @@ fn remote_audio_status(message: String) -> Status {
|
|||||||
Status::internal(message)
|
Status::internal(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::retain_freshest_video_packet;
|
||||||
|
use lesavka_common::lesavka::VideoPacket;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn retain_freshest_video_packet_keeps_only_the_latest_frame() {
|
||||||
|
let mut pending = std::collections::VecDeque::from(vec![
|
||||||
|
VideoPacket {
|
||||||
|
pts: 100,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
VideoPacket {
|
||||||
|
pts: 200,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
VideoPacket {
|
||||||
|
pts: 300,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
let dropped = retain_freshest_video_packet(&mut pending);
|
||||||
|
|
||||||
|
assert_eq!(dropped, 2);
|
||||||
|
assert_eq!(pending.len(), 1);
|
||||||
|
assert_eq!(pending.front().map(|pkt| pkt.pts), Some(300));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,20 @@ fn upstream_stale_drop_budget() -> Duration {
|
|||||||
Duration::from_millis(drop_ms)
|
Duration::from_millis(drop_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(coverage)]
|
||||||
|
fn retain_freshest_video_packet(
|
||||||
|
pending: &mut std::collections::VecDeque<VideoPacket>,
|
||||||
|
) -> usize {
|
||||||
|
if pending.len() <= 1 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let newest = pending.pop_back().expect("non-empty pending video queue");
|
||||||
|
let dropped = pending.len();
|
||||||
|
pending.clear();
|
||||||
|
pending.push_back(newest);
|
||||||
|
dropped
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(coverage)]
|
#[cfg(coverage)]
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl Relay for Handler {
|
impl Relay for Handler {
|
||||||
@ -174,7 +188,10 @@ impl Relay for Handler {
|
|||||||
};
|
};
|
||||||
if let Some(next_packet) = next_packet {
|
if let Some(next_packet) = next_packet {
|
||||||
match next_packet.transpose()? {
|
match next_packet.transpose()? {
|
||||||
Some(pkt) => pending.push_back(pkt),
|
Some(pkt) => {
|
||||||
|
pending.push_back(pkt);
|
||||||
|
let _ = retain_freshest_video_packet(&mut pending);
|
||||||
|
}
|
||||||
None => inbound_closed = true,
|
None => inbound_closed = true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user