diff --git a/Cargo.lock b/Cargo.lock index 106c664..951edc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,7 +60,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.108", + "syn 2.0.109", ] [[package]] @@ -89,9 +89,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.44" +version = "1.2.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" +checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" dependencies = [ "find-msvc-tools", "jobserver", @@ -423,9 +423,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -607,9 +607,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.108" +version = "2.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +checksum = "2f17c7e013e88258aa9543dcbe81aca68a667a9ac37cd69c9fbc07858bfe0e2f" dependencies = [ "proc-macro2", "quote", @@ -633,7 +633,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.108", + "syn 2.0.109", ] [[package]] diff --git a/genvideo/src/main.rs b/genvideo/src/main.rs index b3096c7..0dffc0e 100644 --- a/genvideo/src/main.rs +++ b/genvideo/src/main.rs @@ -183,7 +183,7 @@ struct AudioState { } impl AudioState { - fn new(in_audio_sample_rate: i32, emu_video_frame_rate: i32, output: &mut FFOut) -> Self { + fn new(in_audio_sample_rate: i32, output: &mut FFOut) -> Self { let out_audio_codec = ffmpeg_next::encoder::find(ffmpeg_next::codec::Id::AAC).unwrap(); let mut out_audio_ctx = ffmpeg_next::codec::context::Context::new_with_codec(out_audio_codec); @@ -208,12 +208,12 @@ impl AudioState { )); out_audio_enc.set_channel_layout(ffmpeg_next::ChannelLayout::STEREO); out_audio_enc.set_time_base(audio_time_base); - out_audio_enc.set_rate(48000); + out_audio_enc.set_rate(audio_time_base.1); let out_audio_enc = out_audio_enc.open().unwrap(); let mut in_aframe = FFAFrame::new( ffmpeg_next::format::Sample::I16(ffmpeg_next::format::sample::Type::Packed), - 704, - // dbg!(in_audio_sample_rate / emu_video_frame_rate) as usize, + 1024, + //dbg!(in_audio_sample_rate / emu_video_frame_rate) as usize, ffmpeg_next::ChannelLayout::STEREO, ); in_aframe.set_rate(u32::try_from(in_audio_sample_rate).unwrap()); @@ -223,24 +223,13 @@ impl AudioState { out_audio_enc.channel_layout(), ); out_aframe.set_rate(out_audio_enc.rate()); - let resampler = ffmpeg_next::software::resampler( - ( - in_aframe.format(), - in_aframe.channel_layout(), - in_aframe.rate(), - ), - ( + let resampler = in_aframe + .resampler( out_aframe.format(), out_aframe.channel_layout(), out_aframe.rate(), - ), - ) - .unwrap(); - println!( - "Resample from {} to {}", - in_aframe.rate(), - out_aframe.rate() - ); + ) + .unwrap(); let audio_buf = ringbuf::LocalRb::new(in_aframe.samples() * 2 * 20); Self { @@ -267,25 +256,34 @@ impl AudioState { self.encoded_audio.write_interleaved(output).unwrap(); } } - fn resample(&mut self, drain: bool) { - println!( - "RESAMPLE {:?} {:?}", - self.in_aframe.pts(), - self.out_aframe.pts() - ); - match dbg!(self.resampler.run(&self.in_aframe, &mut self.out_aframe)) { - Ok(Some(delay)) if drain => { - dbg!(delay); - let null_frame = unsafe { FFAFrame::wrap(std::ptr::null_mut()) }; - while let Ok(Some(delay)) = self.resampler.run(&null_frame, &mut self.out_aframe) { - dbg!("2", delay); - if !drain { - break; - } - } + fn resample_and_send(&mut self, output: &mut FFOut, drain: bool) { + match self.resampler.run(&self.in_aframe, &mut self.out_aframe) { + Ok(_) => { + self.in_aframe.set_pts(Some(self.audio_frame_in)); + self.out_aframe.set_pts(Some(self.audio_frame_out)); + self.audio_frame_in += i64::try_from(self.in_aframe.samples()).unwrap(); + self.audio_frame_out += i64::try_from(self.out_aframe.samples()).unwrap(); + self.out_audio_enc.send_frame(&self.out_aframe).unwrap(); + self.writeout(output); } - Err(e) => println!("Resampler error {e}"), - _ => {} + Err(e) => { + println!("Resampler error {e}"); + } + } + loop { + let Some(delay) = self.resampler.delay() else { + break; + }; + if delay.output < 524 && !drain { + break; + } + self.in_aframe.set_pts(Some(self.audio_frame_in)); + self.out_aframe.set_pts(Some(self.audio_frame_out)); + self.resampler.flush(&mut self.out_aframe).unwrap(); + self.audio_frame_in += i64::try_from(self.in_aframe.samples()).unwrap(); + self.audio_frame_out += i64::try_from(self.out_aframe.samples()).unwrap(); + self.out_audio_enc.send_frame(&self.out_aframe).unwrap(); + self.writeout(output); } } fn send_frames(&mut self, emu: &Emulator, output: &mut FFOut) { @@ -295,28 +293,18 @@ impl AudioState { while self.audio_buf.occupied_len() >= self.in_aframe.samples() * 2 { let (_, toconvert, _) = unsafe { self.in_aframe.data_mut(0).align_to_mut::() }; assert_eq!(self.audio_buf.pop_slice(toconvert), toconvert.len()); - dbg!(toconvert.len()); - self.in_aframe.set_pts(Some(self.audio_frame_in)); - self.out_aframe.set_pts(Some(self.audio_frame_out)); - self.audio_frame_in += i64::try_from(self.in_aframe.samples()).unwrap(); - self.audio_frame_out += i64::try_from(self.out_aframe.samples()).unwrap(); - self.resample(false); - dbg!(self.out_aframe.samples()); - self.out_audio_enc.send_frame(&self.out_aframe).unwrap(); + self.resample_and_send(output, false); } }); - self.writeout(output); } fn drain(&mut self, output: &mut FFOut) { while self.audio_buf.occupied_len() > 0 { let (_, toconvert, _) = unsafe { self.in_aframe.data_mut(0).align_to_mut::() }; let len = self.audio_buf.pop_slice(toconvert); toconvert[len..].fill(0); - self.resample(true); - self.out_aframe.set_pts(Some(self.audio_frame_out)); - self.audio_frame_out += i64::try_from(len / 2).unwrap(); - self.out_audio_enc.send_frame(&self.out_aframe).unwrap(); + self.resample_and_send(output, true); } + self.resample_and_send(output, true); self.out_audio_enc.send_eof().unwrap(); self.writeout(output); } @@ -356,19 +344,17 @@ fn main() { let emu_video_framerate = emu.get_video_fps().to_i32().unwrap(); let emu_time_base = Rational::new(1, emu_video_framerate); let audio_sample_rate = emu.get_audio_sample_rate().to_i32().unwrap(); - let aspect_ratio = Rational::from(emu.get_aspect_ratio() as f64); + let aspect_ratio = Rational::from(f64::from(emu.get_aspect_ratio())); let mut video_state = VideoState::new(emu_time_base, aspect_ratio, w, h, pixel_format, &mut output); - let mut audio_state = AudioState::new(audio_sample_rate, emu_video_framerate, &mut output); + let mut audio_state = AudioState::new(audio_sample_rate, &mut output); output.write_header().unwrap(); - let video_stream_time_base = output.stream(0).unwrap().time_base(); - let audio_stream_time_base = output.stream(1).unwrap().time_base(); - video_state - .encoded_video - .set_time_base(video_stream_time_base); - audio_state - .encoded_audio - .set_time_base(audio_stream_time_base); + // video_state + // .encoded_video + // .set_time_base(video_stream_time_base); + // audio_state + // .encoded_audio + // .set_time_base(audio_stream_time_base); let mut frame = Frame::default(); while let Ok(()) = rply