use anyhow::Result;
use tokio::sync::mpsc::Receiver;
use crate::decoder::{audio::AudioFrame, video::VideoFrame};
pub async fn run(
mut video_rx: Receiver<VideoFrame>,
mut audio_rx: Receiver<AudioFrame>,
) -> Result<()> {
tracing::info!("AV sync started");
let mut audio_sample_count: u64 = 0;
let sample_rate: u64 = 44100;
loop {
tokio::select! {
Some(video_frame) = video_rx.recv() => {
let audio_clock_ms = (audio_sample_count * 1000) / sample_rate;
let video_pts_ms = video_frame.pts_ms;
if video_pts_ms + 50 < audio_clock_ms {
tracing::debug!("Dropping late video frame: pts={video_pts_ms}ms clock={audio_clock_ms}ms");
continue;
}
if video_pts_ms > audio_clock_ms + 100 {
tokio::time::sleep(tokio::time::Duration::from_millis(
(video_pts_ms - audio_clock_ms).min(100)
)).await;
}
crate::output::render_frame(&video_frame).await;
}
Some(audio_frame) = audio_rx.recv() => {
audio_sample_count += audio_frame.len() as u64 / 2; crate::output::play_audio(&audio_frame).await;
}
else => break,
}
}
tracing::info!("AV sync completed");
Ok(())
}