diff --git a/Cargo.toml b/Cargo.toml index a350c75..3778c2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,4 +19,4 @@ sdl2 = "^0.32" crossbeam-channel = "^0.4" structopt = "^0.3" # example: ffmpeg_recorder -ffmpeg-next = "4.3.7" +ffmpeg-next = "4.3.8" diff --git a/examples/ffmpeg_recorder.rs b/examples/ffmpeg_recorder.rs index d91759b..3d78e21 100644 --- a/examples/ffmpeg_recorder.rs +++ b/examples/ffmpeg_recorder.rs @@ -13,7 +13,7 @@ use ferretro::retro; use ferretro::retro::ffi::{PixelFormat, GameGeometry, SystemAvInfo, SystemInfo}; use ferretro::retro::wrapper::{LibretroWrapper, Handler}; -use ffmpeg::{format, filter, frame, media, ChannelLayout}; +use ffmpeg::{ChannelLayout, Packet, filter, format, frame, media}; use ffmpeg::util::rational::Rational; struct MyEmulator { @@ -164,7 +164,7 @@ impl MyEmulator { pin_emu } - pub fn run(&mut self) { + pub fn run(&mut self, octx: &mut format::context::Output, frame: i64) { self.retro.run(); let mut vframe = self.video_frames.pop_front().unwrap(); @@ -188,11 +188,30 @@ impl MyEmulator { if self.video_filter.get("out").unwrap().source().failed_requests() > 0 { println!("🎥 failed to get filter output frame"); } - self.video_encoder.encode(&vframe, &mut out).unwrap(); + vframe.set_pts(Some(frame)); + let encode_result = self.video_encoder.encode(&vframe, &mut out).unwrap(); + eprintln!("encoded: {:?}", encode_result); + if encode_result { + out.set_stream(0); + out.write_interleaved(octx).unwrap(); + } + + /* + while self.video_encoder.receive_packet(&mut encoded).is_ok() { + panic!("actually trying to write something!!"); + encoded.set_stream(0); // use stream index... + // rescale_ts?? + encoded.write_interleaved(&mut octx).unwrap(); + } + */ + //eprintln!("packet: {:?}", &out.data()); + //self.video_encoder.flush(&mut out).unwrap(); + //eprintln!("flushed packet: {:?}", &out.data()); } while let Ok(..) = self.audio_filter.get("out").unwrap().sink().frame(&mut aframe) { self.audio_encoder.encode(&aframe, &mut out);//.unwrap(); } + } pub fn load_game(&self, rom: impl AsRef) { @@ -224,9 +243,11 @@ impl retro::wrapper::Handler for MyEmulator { let pitch = pitch as usize; let vplane = vframe.data_mut(0); + /* sus if data.len() == vplane.len() && pitch == stride { vplane.copy_from_slice(&data); } else { + */ for y in 0..(height as usize) { let ffbegin = y * stride; let lrbegin = y * pitch; @@ -235,7 +256,7 @@ impl retro::wrapper::Handler for MyEmulator { &data[lrbegin..(lrbegin + min)] ); } - } + //} self.video_frames.push_back(vframe); } @@ -360,10 +381,20 @@ fn main() -> Fallible<()> { octx.write_header().unwrap(); //for frame in 0..60*10 { - for frame in 0..10 { + for frame in 0..120 { eprintln!("🖼️ frame: {}", frame); - emu.run(); + emu.run(&mut octx, frame); + + let mut encoded = ffmpeg::Packet::empty(); + while emu.video_encoder.receive_packet(&mut encoded).is_ok() { + panic!("actually trying to write something!!"); + encoded.set_stream(0); // use stream index... + // rescale_ts?? + encoded.write_interleaved(&mut octx).unwrap(); + } } + let mut packet = Packet::empty(); + eprintln!("flushed: {:?}", emu.video_encoder.flush(&mut packet).unwrap()); octx.write_trailer().unwrap(); Ok(()) diff --git a/examples/sdl2_emulator.rs b/examples/sdl2_emulator.rs index 8ca7db2..293dc90 100644 --- a/examples/sdl2_emulator.rs +++ b/examples/sdl2_emulator.rs @@ -158,7 +158,7 @@ impl MyEmulator { // similar hack to the sample rate, make sure we don't divide by zero. let mut spf = 1.0 / self.av_info.timing.fps; - if spf.is_nan() { + if spf.is_nan() || spf.is_infinite() { spf = 1.0 / 60.0; } Duration::from_secs_f64(spf)