From 7c03aac38886ed647454a2767a7aa20ba8eb8711 Mon Sep 17 00:00:00 2001 From: Viv Lim Date: Tue, 27 Jul 2021 00:50:11 -0700 Subject: [PATCH] Don't panic if the emulator doesn't have frames ready to render, use angrylion with parallel-n64 --- examples/ffmpeg_recorder.rs | 144 +++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 60 deletions(-) diff --git a/examples/ffmpeg_recorder.rs b/examples/ffmpeg_recorder.rs index e45ffa8..a45d2a0 100644 --- a/examples/ffmpeg_recorder.rs +++ b/examples/ffmpeg_recorder.rs @@ -13,6 +13,8 @@ use ferretro::retro; use ferretro::retro::ffi::{PixelFormat, GameGeometry, SystemAvInfo, SystemInfo}; use ferretro::retro::wrapper::{LibretroWrapper, Handler}; +use ferretro::retro::wrapped_types::{Variable2}; + use ffmpeg::{ChannelLayout, Packet, codec, filter, format, frame, media}; use ffmpeg::util::rational::Rational; @@ -278,71 +280,77 @@ static bool ffmpeg_init_config(struct ff_config_param *params, self.frame += 1; self.retro.run(); - let mut vframe = self.video_frames.pop_front().unwrap(); - vframe.set_pts(Some(frame)); - eprintln!("🎞 queue frame pts {:?}", vframe.pts()); - self.video_filter.get("in").unwrap().source().add(&vframe).unwrap(); - let mut filtered_vframe = frame::Video::empty(); + match self.video_frames.pop_front() { + Some(mut vframe) => { + vframe.set_pts(Some(frame)); + eprintln!("🎞 queue frame pts {:?}", vframe.pts()); + self.video_filter.get("in").unwrap().source().add(&vframe).unwrap(); + let mut filtered_vframe = frame::Video::empty(); - loop { - match self.video_filter.get("out").unwrap().sink().frame(&mut filtered_vframe) { - Ok(..) => { - eprintln!("đŸŽĨ Got filtered video frame {}x{} pts {:?}", filtered_vframe.width(), filtered_vframe.height(), filtered_vframe.pts()); - if self.video_filter.get("in").unwrap().source().failed_requests() > 0 { - println!("đŸŽĨ failed to put filter input frame"); + loop { + match self.video_filter.get("out").unwrap().sink().frame(&mut filtered_vframe) { + Ok(..) => { + eprintln!("đŸŽĨ Got filtered video frame {}x{} pts {:?}", filtered_vframe.width(), filtered_vframe.height(), filtered_vframe.pts()); + if self.video_filter.get("in").unwrap().source().failed_requests() > 0 { + println!("đŸŽĨ failed to put filter input frame"); + } + //filtered_vframe.set_pts(Some(frame)); + self.video_encoder.send_frame(&filtered_vframe).unwrap(); + + self.receive_and_write_packets(EncoderToWriteFrom::Video); + }, + Err(e) => { + eprintln!("Error getting filtered video frame: {:?}", e); + break; + } } - //filtered_vframe.set_pts(Some(frame)); - self.video_encoder.send_frame(&filtered_vframe).unwrap(); - - self.receive_and_write_packets(EncoderToWriteFrom::Video); - }, - Err(e) => { - eprintln!("Error getting filtered video frame: {:?}", e); - break; } - } + + // Assumption: if there is a video frame, there is an audio frame. + let mut aframe = frame::Audio::new( + format::Sample::I16(format::sample::Type::Packed), + self.audio_buf.len(), + ChannelLayout::STEREO + ); + aframe.set_channels(2); + aframe.set_rate(44100); + let aplane: &mut [(i16, i16)] = aframe.plane_mut(0); + eprintln!("Audio buffer length {} -> {}", self.audio_buf.len(), aplane.len()); + aplane.copy_from_slice(self.audio_buf.as_ref()); + //eprintln!("src: {:?}, dest: {:?}", self.audio_buf, aplane); + self.audio_buf.clear(); + + eprintln!("frame audio: {:?}", aframe); + + //aframe.set_pts(Some(frame)); + eprintln!("🎞 queue frame pts {:?}", aframe.pts()); + self.audio_filter.get("in").unwrap().source().add(&aframe).unwrap(); + + let mut filtered_aframe = frame::Audio::empty(); + loop { + match self.audio_filter.get("out").unwrap().sink().frame(&mut filtered_aframe) { + Ok(..) => { + eprintln!("🔊 Got filtered audio frame {:?} pts {:?}", filtered_aframe, filtered_aframe.pts()); + if self.audio_filter.get("in").unwrap().source().failed_requests() > 0 { + println!("đŸŽĨ failed to put filter input frame"); + } + //let faplane: &[f32] = filtered_aframe.plane(0); + filtered_aframe.set_pts(Some(frame)); + + self.audio_encoder.send_frame(&filtered_aframe).unwrap(); + self.receive_and_write_packets(EncoderToWriteFrom::Audio); + }, + Err(e) => { + eprintln!("Error getting filtered audio frame: {:?}", e); + break; + } + } + } + }, + None => println!("Video not ready during frame {}", self.frame) } - let mut aframe = frame::Audio::new( - format::Sample::I16(format::sample::Type::Packed), - self.audio_buf.len(), - ChannelLayout::STEREO - ); - aframe.set_channels(2); - aframe.set_rate(44100); - let aplane: &mut [(i16, i16)] = aframe.plane_mut(0); - eprintln!("Audio buffer length {} -> {}", self.audio_buf.len(), aplane.len()); - aplane.copy_from_slice(self.audio_buf.as_ref()); - //eprintln!("src: {:?}, dest: {:?}", self.audio_buf, aplane); - self.audio_buf.clear(); - - eprintln!("frame audio: {:?}", aframe); - - //aframe.set_pts(Some(frame)); - eprintln!("🎞 queue frame pts {:?}", aframe.pts()); - self.audio_filter.get("in").unwrap().source().add(&aframe).unwrap(); - - let mut filtered_aframe = frame::Audio::empty(); - loop { - match self.audio_filter.get("out").unwrap().sink().frame(&mut filtered_aframe) { - Ok(..) => { - eprintln!("🔊 Got filtered audio frame {:?} pts {:?}", filtered_aframe, filtered_aframe.pts()); - if self.audio_filter.get("in").unwrap().source().failed_requests() > 0 { - println!("đŸŽĨ failed to put filter input frame"); - } - //let faplane: &[f32] = filtered_aframe.plane(0); - filtered_aframe.set_pts(Some(frame)); - - self.audio_encoder.send_frame(&filtered_aframe).unwrap(); - self.receive_and_write_packets(EncoderToWriteFrom::Audio); - }, - Err(e) => { - eprintln!("Error getting filtered audio frame: {:?}", e); - break; - } - } - } } @@ -468,9 +476,25 @@ impl retro::wrapper::Handler for MyEmulator { } + fn get_variable(&mut self, key: &str) -> Option { + match key { + "beetle_saturn_analog_stick_deadzone" => Some("15%".to_string()), + "parallel-n64-gfxplugin" => Some("angrylion".to_string()), + "parallel-n64-astick-deadzone" => Some("15%".to_string()), + _ => None, + } + } + + fn set_variables(&mut self, variables: Vec) -> bool { + for v in variables { + eprintln!("{:?}", v); + } + true + } + fn log_print(&mut self, level: retro::ffi::LogLevel, msg: &str) { eprint!("🕹ī¸ [{:?}] {}", level, msg); -} + } } #[derive(StructOpt)]