chore(stereo): 优化播放设备重初始化
This commit is contained in:
@@ -217,6 +217,8 @@ pub async fn run_master(master_role: ChannelRole) -> Result<()> {
|
|||||||
let wait = target_ts - now;
|
let wait = target_ts - now;
|
||||||
if wait > 1000 {
|
if wait > 1000 {
|
||||||
tokio::time::sleep(Duration::from_micros(wait as u64)).await;
|
tokio::time::sleep(Duration::from_micros(wait as u64)).await;
|
||||||
|
} else {
|
||||||
|
// 小于 1ms,直接播放,让播放时机稍微早一点点
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -170,7 +170,6 @@ async fn handle_connection(role: ChannelRole) -> Result<()> {
|
|||||||
last_seq = Some(pkt.seq);
|
last_seq = Some(pkt.seq);
|
||||||
|
|
||||||
// 精确等待到播放时间
|
// 精确等待到播放时间
|
||||||
// 策略: 距离远时 sleep,距离近时忙等
|
|
||||||
loop {
|
loop {
|
||||||
let now = now_us();
|
let now = now_us();
|
||||||
let current_server_time_precise = clock.lock().await.to_server_time(now);
|
let current_server_time_precise = clock.lock().await.to_server_time(now);
|
||||||
@@ -181,14 +180,10 @@ async fn handle_connection(role: ChannelRole) -> Result<()> {
|
|||||||
|
|
||||||
let wait_us = (pkt.timestamp - current_server_time_precise) as u64;
|
let wait_us = (pkt.timestamp - current_server_time_precise) as u64;
|
||||||
|
|
||||||
if wait_us > 5000 {
|
if wait_us > 1000 {
|
||||||
// 等待时间 >5ms: sleep 大部分时间
|
tokio::time::sleep(Duration::from_micros(wait_us as u64)).await;
|
||||||
tokio::time::sleep(Duration::from_micros(wait_us - 3000)).await;
|
|
||||||
} else if wait_us > 1000 {
|
|
||||||
// 等待时间 1-5ms: yield 让出 CPU
|
|
||||||
tokio::task::yield_now().await;
|
|
||||||
} else {
|
} else {
|
||||||
// 等待时间 <1ms: 直接 break,让播放时机稍微早一点点
|
// 小于 1ms,直接播放,让播放时机稍微早一点点
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,18 +52,19 @@ fn setup_pcm(pcm: &PCM, sample_rate: u32, channels: u16) -> Result<()> {
|
|||||||
hwp.set_rate(sample_rate, alsa::ValueOr::Nearest)?;
|
hwp.set_rate(sample_rate, alsa::ValueOr::Nearest)?;
|
||||||
hwp.set_channels(channels as u32)?;
|
hwp.set_channels(channels as u32)?;
|
||||||
|
|
||||||
// // 设置较大的缓冲区以减少由于调度抖动导致的断音
|
// 设置较大的缓冲区以减少由于调度抖动和设备重初始化导致的断音/卡顿
|
||||||
// // 48000Hz * 0.2s = 9600 samples
|
// 使用 100ms 缓冲区,既能防止 underrun,又不会引入过大延迟
|
||||||
// let buffer_size = (sample_rate as f64 * 0.2) as u32;
|
let buffer_size = (sample_rate as f64 * 0.1) as u32; // 100ms 缓冲
|
||||||
// let period_size = buffer_size / 4;
|
let period_size = buffer_size / 4; // 25ms 周期
|
||||||
// hwp.set_buffer_size_near(buffer_size as alsa::pcm::Frames)?;
|
hwp.set_buffer_size_near(buffer_size as alsa::pcm::Frames)?;
|
||||||
// hwp.set_period_size_near(period_size as alsa::pcm::Frames, alsa::ValueOr::Nearest)?;
|
hwp.set_period_size_near(period_size as alsa::pcm::Frames, alsa::ValueOr::Nearest)?;
|
||||||
|
|
||||||
pcm.hw_params(&hwp).context("Failed to set HwParams")?;
|
pcm.hw_params(&hwp).context("Failed to set HwParams")?;
|
||||||
|
|
||||||
let swp = pcm.sw_params_current()?;
|
let swp = pcm.sw_params_current()?;
|
||||||
// 设置 start_threshold 为 buffer_size 的一半,确保缓冲区有足够数据再开始播放
|
// 设置 start_threshold,当缓冲区有 1 个 period 数据时就开始播放
|
||||||
// swp.set_start_threshold(buffer_size as alsa::pcm::Frames / 2)?;
|
// 这样可以快速启动,同时保持足够的缓冲余量
|
||||||
|
swp.set_start_threshold(period_size as alsa::pcm::Frames)?;
|
||||||
pcm.sw_params(&swp)?;
|
pcm.sw_params(&swp)?;
|
||||||
pcm.prepare()?;
|
pcm.prepare()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user