diff --git a/src/player.rs b/src/player.rs index c48f7cd..7151270 100644 --- a/src/player.rs +++ b/src/player.rs @@ -6,6 +6,7 @@ use cpal::{ FromSample, SizedSample, }; use ffmpeg::{ + codec::discard, format::{input, Pixel}, media::Type, software::{resampling, scaling}, @@ -47,7 +48,9 @@ impl AsRef<[u8]> for VideoFrame { } } -fn cpal(audio_queue_lock: Arc>>) -> cpal::SupportedStreamConfig { +fn cpal( + audio_queue_lock: Arc>>, +) -> (cpal::SupportedStreamConfig, Box) { let host = cpal::default_host(); let device = host .default_output_device() @@ -57,58 +60,36 @@ fn cpal(audio_queue_lock: Arc>>) -> cpal::SupportedStreamCon .expect("failed to get default audio output config"); println!("{:?}: {:?}", device.name(), config); - { + let stream = { let config = config.clone(); - thread::spawn(move || { - match config.sample_format() { - cpal::SampleFormat::I8 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - cpal::SampleFormat::I16 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - // cpal::SampleFormat::I24 => cpal_thread::(device, config.into(), audio_queue_lock), - cpal::SampleFormat::I32 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - // cpal::SampleFormat::I48 => cpal_thread::(device, config.into(), audio_queue_lock), - cpal::SampleFormat::I64 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - cpal::SampleFormat::U8 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - cpal::SampleFormat::U16 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - // cpal::SampleFormat::U24 => cpal_thread::(device, config.into(), audio_queue_lock), - cpal::SampleFormat::U32 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - // cpal::SampleFormat::U48 => cpal_thread::(device, config.into(), audio_queue_lock), - cpal::SampleFormat::U64 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - cpal::SampleFormat::F32 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - cpal::SampleFormat::F64 => { - cpal_thread::(device, config.into(), audio_queue_lock) - } - sample_format => panic!("unsupported sample format '{sample_format}'"), - } - .unwrap(); - }); - } + match config.sample_format() { + cpal::SampleFormat::I8 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::I16 => cpal_stream::(device, config.into(), audio_queue_lock), + // cpal::SampleFormat::I24 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::I32 => cpal_stream::(device, config.into(), audio_queue_lock), + // cpal::SampleFormat::I48 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::I64 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::U8 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::U16 => cpal_stream::(device, config.into(), audio_queue_lock), + // cpal::SampleFormat::U24 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::U32 => cpal_stream::(device, config.into(), audio_queue_lock), + // cpal::SampleFormat::U48 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::U64 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::F32 => cpal_stream::(device, config.into(), audio_queue_lock), + cpal::SampleFormat::F64 => cpal_stream::(device, config.into(), audio_queue_lock), + sample_format => panic!("unsupported sample format '{sample_format}'"), + } + .unwrap() + }; - config + (config, stream) } -fn cpal_thread( +fn cpal_stream( device: cpal::Device, config: cpal::StreamConfig, audio_queue_lock: Arc>>, -) -> Result<(), Box> +) -> Result, Box> where T: SizedSample + FromSample, { @@ -135,25 +116,19 @@ where } } }; - let err_fn = |err| eprintln!("an error occurred on stream: {}", err); - let stream = device.build_output_stream(&config, data_fn, err_fn, None)?; - stream.play()?; - - loop { - //TODO: move this code to ffmpeg_thread so we don't have to sleep here? - thread::sleep(Duration::from_millis(1000)); - } + Ok(Box::new(stream)) } fn ffmpeg_thread>( path: P, player_rx: mpsc::Receiver, video_frame_lock: Arc>>, - audio_config: cpal::SupportedStreamConfig, - audio_queue_lock: Arc>>, -) -> Result<(), ffmpeg::Error> { +) -> Result<(), Box> { + let audio_queue_lock = Arc::new(Mutex::new(VecDeque::new())); + let (audio_config, cpal_stream) = cpal(audio_queue_lock.clone()); + let mut ictx = input(&path)?; let video_stream = ictx @@ -169,90 +144,107 @@ fn ffmpeg_thread>( let video_format = video_decoder.format(); let video_width = video_decoder.width(); let video_height = video_decoder.height(); - let (raw_frame_tx, raw_frame_rx) = mpsc::channel(); - thread::spawn(move || -> Result<(), ffmpeg::Error> { - let mut video_scaler = scaling::context::Context::get( - video_format, - video_width, - video_height, - Pixel::RGBA, - video_width, - video_height, - scaling::Flags::FAST_BILINEAR, - )?; + let (raw_frame_tx, raw_frame_rx) = mpsc::channel::