ace_player/sync/
av_sync.rs1use anyhow::Result;
6use tokio::sync::mpsc::Receiver;
7use crate::decoder::{audio::AudioFrame, video::VideoFrame};
8
9pub async fn run(
11 mut video_rx: Receiver<VideoFrame>,
12 mut audio_rx: Receiver<AudioFrame>,
13) -> Result<()> {
14 tracing::info!("AV sync started");
15
16 let mut audio_sample_count: u64 = 0;
18 let sample_rate: u64 = 44100;
19
20 loop {
21 tokio::select! {
22 Some(video_frame) = video_rx.recv() => {
23 let audio_clock_ms = (audio_sample_count * 1000) / sample_rate;
25 let video_pts_ms = video_frame.pts_ms;
26
27 if video_pts_ms + 50 < audio_clock_ms {
29 tracing::debug!("Dropping late video frame: pts={video_pts_ms}ms clock={audio_clock_ms}ms");
30 continue;
31 }
32 if video_pts_ms > audio_clock_ms + 100 {
33 tokio::time::sleep(tokio::time::Duration::from_millis(
35 (video_pts_ms - audio_clock_ms).min(100)
36 )).await;
37 }
38
39 crate::output::render_frame(&video_frame).await;
41 }
42
43 Some(audio_frame) = audio_rx.recv() => {
44 audio_sample_count += audio_frame.len() as u64 / 2; crate::output::play_audio(&audio_frame).await;
46 }
47
48 else => break,
49 }
50 }
51
52 tracing::info!("AV sync completed");
53 Ok(())
54}