//! # Jitter Buffer - 抖动缓冲区 //! //! 用于音频流的抖动缓冲和包重排序。 //! //! ## 功能 //! - 自适应缓冲区大小 //! - 乱序包重排 //! - 丢包检测和统计 //! - 延迟统计 use crate::net::protocol::AudioPacket; use std::cmp::Ordering; use std::collections::{BTreeMap, VecDeque}; impl PartialEq for AudioPacket { fn eq(&self, other: &Self) -> bool { self.timestamp == other.timestamp } } impl Eq for AudioPacket {} impl Ord for AudioPacket { fn cmp(&self, other: &Self) -> Ordering { other.timestamp.cmp(&self.timestamp) } } impl PartialOrd for AudioPacket { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } /// Jitter Buffer 统计信息 #[derive(Debug, Clone, Default)] pub struct JitterStats { /// 总接收包数 pub received: u64, /// 总丢包数 pub lost: u64, /// 总播放包数 pub played: u64, /// 迟到的包数(到达时已过播放时间) pub late: u64, /// 重复包数 pub duplicate: u64, /// 当前缓冲区大小(包数) pub buffer_size: usize, /// 最小延迟(微秒) pub min_delay: u128, /// 最大延迟(微秒) pub max_delay: u128, /// 平均延迟(微秒) pub avg_delay: u128, } impl JitterStats { /// 计算丢包率(百分比) pub fn loss_rate(&self) -> f64 { if self.received + self.lost == 0 { return 0.0; } (self.lost as f64 / (self.received + self.lost) as f64) * 100.0 } } /// Jitter Buffer 配置 #[derive(Debug, Clone)] pub struct JitterConfig { /// 最小缓冲区大小(包数) pub min_buffer_size: usize, /// 最大缓冲区大小(包数) pub max_buffer_size: usize, /// 目标缓冲区大小(包数) pub target_buffer_size: usize, /// 自适应调整间隔(包数) pub adapt_interval: usize, /// 最大容忍延迟(微秒) pub max_tolerable_delay: u128, } impl Default for JitterConfig { fn default() -> Self { Self { min_buffer_size: 2, max_buffer_size: 20, target_buffer_size: 5, adapt_interval: 50, max_tolerable_delay: 100_000, // 100ms } } } /// Jitter Buffer - 用于音频流的抖动缓冲 pub struct JitterBuffer { /// 配置 config: JitterConfig, /// 缓冲区(按时间戳排序) buffer: BTreeMap, /// 统计信息 stats: JitterStats, /// 期望的下一个序列号 expected_seq: u32, /// 是否已接收第一个包 first_packet_received: bool, /// 延迟样本窗口(用于自适应) delay_samples: VecDeque, /// 自适应计数器 adapt_counter: usize, /// 上次播放的时间戳 last_played_timestamp: u128, } impl JitterBuffer { /// 创建新的 Jitter Buffer pub fn new(config: JitterConfig) -> Self { Self { config, buffer: BTreeMap::new(), stats: JitterStats::default(), expected_seq: 0, first_packet_received: false, delay_samples: VecDeque::with_capacity(100), adapt_counter: 0, last_played_timestamp: 0, } } /// 使用默认配置创建 pub fn default() -> Self { Self::new(JitterConfig::default()) } /// 插入音频包 pub fn push(&mut self, packet: AudioPacket, arrival_time: u128) { // 检测重复包 if self.buffer.contains_key(&packet.timestamp) { self.stats.duplicate += 1; return; } // 初始化序列号 if !self.first_packet_received { self.expected_seq = packet.seq.wrapping_add(1); self.first_packet_received = true; } else { // 检测丢包 let seq_diff = packet.seq.wrapping_sub(self.expected_seq); if seq_diff > 0 && seq_diff < 1000 { // 允许一定的序列号跳跃(处理回环) self.stats.lost += seq_diff as u64; } self.expected_seq = packet.seq.wrapping_add(1); } // 检查是否迟到 if self.last_played_timestamp > 0 && packet.timestamp < self.last_played_timestamp { self.stats.late += 1; return; } // 超过最大容忍延迟,直接丢弃 if packet.timestamp < arrival_time && arrival_time - packet.timestamp > self.config.max_tolerable_delay { self.stats.late += 1; return; } let delay = if packet.timestamp >= arrival_time { packet.timestamp - arrival_time } else { 0 // 包到达时已经过了播放时间 }; self.update_delay_stats(delay); // 插入缓冲区 self.buffer.insert(packet.timestamp, packet); self.stats.received += 1; self.stats.buffer_size = self.buffer.len(); // 自适应调整 self.adapt_counter += 1; if self.adapt_counter >= self.config.adapt_interval { self.adapt_buffer_size(); self.adapt_counter = 0; } } /// 获取下一个应该播放的包 /// /// # Arguments /// * `current_time` - 当前服务器时间 /// /// # Returns /// * `Some(packet)` - 如果有包应该播放 /// * `None` - 如果缓冲区为空或还没到播放时间 pub fn pop(&mut self, current_time: u128) -> Option { // 如果缓冲区为空,直接返回 if self.buffer.is_empty() { return None; } // 检查缓冲区是否达到最小大小 if self.buffer.len() < self.config.target_buffer_size && !self.should_drain() { return None; } // 获取最早的包 if let Some((×tamp, _)) = self.buffer.iter().next() { // 检查是否到达播放时间 if current_time >= timestamp { let packet = self.buffer.remove(×tamp).unwrap(); self.last_played_timestamp = timestamp; self.stats.played += 1; self.stats.buffer_size = self.buffer.len(); return Some(packet); } } None } /// 强制获取下一个包(无论时间) pub fn pop_next(&mut self) -> Option { if let Some((×tamp, _)) = self.buffer.iter().next() { let packet = self.buffer.remove(×tamp).unwrap(); self.last_played_timestamp = timestamp; self.stats.played += 1; self.stats.buffer_size = self.buffer.len(); return Some(packet); } None } /// 查看下一个包的播放时间(不移除) pub fn peek_next_timestamp(&self) -> Option { self.buffer.keys().next().copied() } /// 获取缓冲区大小 pub fn len(&self) -> usize { self.buffer.len() } /// 检查缓冲区是否为空 pub fn is_empty(&self) -> bool { self.buffer.is_empty() } /// 获取统计信息 pub fn stats(&self) -> &JitterStats { &self.stats } /// 重置统计信息 pub fn reset_stats(&mut self) { self.stats = JitterStats::default(); self.stats.buffer_size = self.buffer.len(); } /// 清空缓冲区 pub fn clear(&mut self) { self.buffer.clear(); self.stats.buffer_size = 0; self.first_packet_received = false; self.last_played_timestamp = 0; } /// 检查是否应该排空缓冲区(处理长时间没有新包的情况) fn should_drain(&self) -> bool { // 如果缓冲区有包且已经等了很久,就开始播放 !self.buffer.is_empty() && self.buffer.len() >= self.config.min_buffer_size } /// 更新延迟统计 fn update_delay_stats(&mut self, delay: u128) { // 更新最小/最大延迟 if self.stats.received == 0 { self.stats.min_delay = delay; self.stats.max_delay = delay; self.stats.avg_delay = delay; } else { self.stats.min_delay = self.stats.min_delay.min(delay); self.stats.max_delay = self.stats.max_delay.max(delay); // 滑动平均 self.stats.avg_delay = (self.stats.avg_delay * 9 + delay) / 10; } // 保存延迟样本用于自适应 self.delay_samples.push_back(delay); if self.delay_samples.len() > 100 { self.delay_samples.pop_front(); } } /// 自适应调整缓冲区大小 fn adapt_buffer_size(&mut self) { if self.delay_samples.len() < 10 { return; } // 计算延迟方差(抖动) let avg = self.stats.avg_delay; let variance: f64 = self .delay_samples .iter() .map(|&d| { let diff = d as i128 - avg as i128; (diff * diff) as f64 }) .sum::() / self.delay_samples.len() as f64; let jitter = variance.sqrt(); // 根据抖动调整目标缓冲区大小 // 抖动大 -> 增加缓冲区 // 抖动小 -> 减少缓冲区 let target = if jitter > 50_000.0 { // 高抖动(>50ms 标准差) self.config.target_buffer_size + 2 } else if jitter < 10_000.0 { // 低抖动(<10ms 标准差) self.config.target_buffer_size.saturating_sub(1) } else { self.config.target_buffer_size }; // 限制在最小/最大范围内 self.config.target_buffer_size = target .max(self.config.min_buffer_size) .min(self.config.max_buffer_size); } }