Don't panic if the emulator doesn't have frames ready to render, use angrylion with parallel-n64
This commit is contained in:
parent
ee9678af68
commit
7c03aac388
|
@ -13,6 +13,8 @@ use ferretro::retro;
|
||||||
use ferretro::retro::ffi::{PixelFormat, GameGeometry, SystemAvInfo, SystemInfo};
|
use ferretro::retro::ffi::{PixelFormat, GameGeometry, SystemAvInfo, SystemInfo};
|
||||||
use ferretro::retro::wrapper::{LibretroWrapper, Handler};
|
use ferretro::retro::wrapper::{LibretroWrapper, Handler};
|
||||||
|
|
||||||
|
use ferretro::retro::wrapped_types::{Variable2};
|
||||||
|
|
||||||
use ffmpeg::{ChannelLayout, Packet, codec, filter, format, frame, media};
|
use ffmpeg::{ChannelLayout, Packet, codec, filter, format, frame, media};
|
||||||
use ffmpeg::util::rational::Rational;
|
use ffmpeg::util::rational::Rational;
|
||||||
|
|
||||||
|
@ -278,71 +280,77 @@ static bool ffmpeg_init_config(struct ff_config_param *params,
|
||||||
self.frame += 1;
|
self.frame += 1;
|
||||||
self.retro.run();
|
self.retro.run();
|
||||||
|
|
||||||
let mut vframe = self.video_frames.pop_front().unwrap();
|
match self.video_frames.pop_front() {
|
||||||
vframe.set_pts(Some(frame));
|
Some(mut vframe) => {
|
||||||
eprintln!("🎞 queue frame pts {:?}", vframe.pts());
|
vframe.set_pts(Some(frame));
|
||||||
self.video_filter.get("in").unwrap().source().add(&vframe).unwrap();
|
eprintln!("🎞 queue frame pts {:?}", vframe.pts());
|
||||||
let mut filtered_vframe = frame::Video::empty();
|
self.video_filter.get("in").unwrap().source().add(&vframe).unwrap();
|
||||||
|
let mut filtered_vframe = frame::Video::empty();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.video_filter.get("out").unwrap().sink().frame(&mut filtered_vframe) {
|
match self.video_filter.get("out").unwrap().sink().frame(&mut filtered_vframe) {
|
||||||
Ok(..) => {
|
Ok(..) => {
|
||||||
eprintln!("🎥 Got filtered video frame {}x{} pts {:?}", filtered_vframe.width(), filtered_vframe.height(), filtered_vframe.pts());
|
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 {
|
if self.video_filter.get("in").unwrap().source().failed_requests() > 0 {
|
||||||
println!("🎥 failed to put filter input frame");
|
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<String> {
|
||||||
|
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<Variable2>) -> bool {
|
||||||
|
for v in variables {
|
||||||
|
eprintln!("{:?}", v);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn log_print(&mut self, level: retro::ffi::LogLevel, msg: &str) {
|
fn log_print(&mut self, level: retro::ffi::LogLevel, msg: &str) {
|
||||||
eprint!("🕹️ [{:?}] {}", level, msg);
|
eprint!("🕹️ [{:?}] {}", level, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
|
|
Loading…
Reference in New Issue