synced a/v on some players at least. ideally i'd like to write the header with the right time bases set.

This commit is contained in:
Viv Lim 2021-07-26 00:42:06 -07:00
parent 57530da214
commit ea771c8dd7
1 changed files with 32 additions and 15 deletions

View File

@ -82,7 +82,7 @@ fn audio_filter(
) -> Result<filter::Graph, ffmpeg::Error> { ) -> Result<filter::Graph, ffmpeg::Error> {
let mut afilter = filter::Graph::new(); let mut afilter = filter::Graph::new();
let sample_rate = if sample_rate == 0.0 { 32040.0 } else { sample_rate }; let sample_rate = if sample_rate == 0.0 { 32040.0 } else { sample_rate };
let args = format!("sample_rate={}:sample_fmt=s16:channel_layout=stereo", sample_rate); let args = format!("sample_rate={}:sample_fmt=s16:channel_layout=stereo:time_base=1/60", sample_rate);
eprintln!("🔊 filter args: {}", args); eprintln!("🔊 filter args: {}", args);
afilter.add(&filter::find("abuffer").unwrap(), "in", &args)?; afilter.add(&filter::find("abuffer").unwrap(), "in", &args)?;
//aresample? //aresample?
@ -145,14 +145,16 @@ let wavname = Path::new("out.wav");
let acodec = ffmpeg::encoder::find(detected_acodec).unwrap().audio().unwrap(); let acodec = ffmpeg::encoder::find(detected_acodec).unwrap().audio().unwrap();
let mut video_output = octx.add_stream(vcodec).unwrap(); let mut video_output = octx.add_stream(vcodec).unwrap();
video_output.set_time_base(Rational::new(1, 60));
let mut video_encoder = video_output.codec().encoder().video().unwrap(); let mut video_encoder = video_output.codec().encoder().video().unwrap();
video_encoder.set_bit_rate(2560000); video_encoder.set_bit_rate(2560000);
video_encoder.set_format(video_encoder.codec().unwrap().video().unwrap().formats().unwrap().nth(0).unwrap()); video_encoder.set_format(video_encoder.codec().unwrap().video().unwrap().formats().unwrap().nth(0).unwrap());
video_encoder.set_time_base(Rational::new(1, fps_int)); video_encoder.set_time_base(Rational::new(1, 60));
video_output.set_time_base(Rational::new(1, fps_int)); video_encoder.set_frame_rate(Some(Rational::new(60, 1)));
video_encoder.set_frame_rate(av_info.timing.fps.into());
//video_encoder.set_frame_rate(av_info.timing.fps.into());
if av_info.geometry.base_height == 0 && av_info.geometry.base_width == 0 { if av_info.geometry.base_height == 0 && av_info.geometry.base_width == 0 {
av_info.geometry.base_width = 320; av_info.geometry.base_width = 320;
@ -197,8 +199,8 @@ static bool ffmpeg_init_config(struct ff_config_param *params,
audio_encoder.set_channels(2); audio_encoder.set_channels(2);
audio_encoder.set_channel_layout(ChannelLayout::STEREO); audio_encoder.set_channel_layout(ChannelLayout::STEREO);
audio_encoder.set_format(audio_encoder.codec().unwrap().audio().unwrap().formats().unwrap().nth(0).unwrap()); audio_encoder.set_format(audio_encoder.codec().unwrap().audio().unwrap().formats().unwrap().nth(0).unwrap());
audio_encoder.set_time_base(Rational::new(1, fps_int)); audio_encoder.set_time_base(Rational::new(1, 60));
audio_output.set_time_base(Rational::new(1, fps_int)); audio_output.set_time_base(Rational::new(1, 60));
let mut audio_encoder = audio_encoder.open_as(acodec).unwrap(); let mut audio_encoder = audio_encoder.open_as(acodec).unwrap();
//audio_output.set_parameters(&audio_encoder); //audio_output.set_parameters(&audio_encoder);
@ -250,8 +252,18 @@ static bool ffmpeg_init_config(struct ff_config_param *params,
Ok(..) => { Ok(..) => {
//if encoded_packet.size() > 0 { //if encoded_packet.size() > 0 {
encoded_packet.set_stream(stream_index); encoded_packet.set_stream(stream_index);
eprintln!("Writing packet, pts {:?} dts {:?} size {}", encoded_packet.pts(), encoded_packet.dts(), encoded_packet.size()); eprintln!("📦 Writing packet, pts {:?} dts {:?} size {}", encoded_packet.pts(), encoded_packet.dts(), encoded_packet.size());
match encoded_packet.write(&mut self.octx) { if let EncoderToWriteFrom::Video = encoder{
//encoded_packet.rescale_ts(Rational(1, 60), Rational(1, 44100)); // slow, ~30fps
encoded_packet.rescale_ts(Rational(1, 60), Rational(1, 15360));
}
if let EncoderToWriteFrom::Audio = encoder{
//encoded_packet.rescale_ts(Rational(1, 60), Rational(1, 44100)); // slow, ~30fps
encoded_packet.rescale_ts(Rational(1, 60), Rational(1, 44100));
}
eprintln!("📦 rescaled , pts {:?} dts {:?} size {}", encoded_packet.pts(), encoded_packet.dts(), encoded_packet.size());
match encoded_packet.write_interleaved(&mut self.octx) {
Ok(..) => eprintln!("Write OK"), Ok(..) => eprintln!("Write OK"),
Err(e) => eprintln!("Error writing: {}", e), Err(e) => eprintln!("Error writing: {}", e),
} }
@ -274,17 +286,19 @@ static bool ffmpeg_init_config(struct ff_config_param *params,
self.retro.run(); self.retro.run();
let mut vframe = self.video_frames.pop_front().unwrap(); 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(); self.video_filter.get("in").unwrap().source().add(&vframe).unwrap();
let mut filtered_vframe = frame::Video::empty(); 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"); 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)); //filtered_vframe.set_pts(Some(frame));
self.video_encoder.send_frame(&filtered_vframe).unwrap(); self.video_encoder.send_frame(&filtered_vframe).unwrap();
self.receive_and_write_packets(EncoderToWriteFrom::Video); self.receive_and_write_packets(EncoderToWriteFrom::Video);
@ -312,20 +326,21 @@ static bool ffmpeg_init_config(struct ff_config_param *params,
eprintln!("frame audio: {:?}", aframe); 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(); self.audio_filter.get("in").unwrap().source().add(&aframe).unwrap();
let mut filtered_aframe = frame::Audio::empty(); let mut filtered_aframe = frame::Audio::empty();
loop { loop {
match self.audio_filter.get("out").unwrap().sink().frame(&mut filtered_aframe) { match self.audio_filter.get("out").unwrap().sink().frame(&mut filtered_aframe) {
Ok(..) => { Ok(..) => {
eprintln!("Got filtered audio frame {:?}", filtered_aframe); eprintln!("🔊 Got filtered audio frame {:?} pts {:?}", filtered_aframe, filtered_aframe.pts());
if self.audio_filter.get("in").unwrap().source().failed_requests() > 0 { if self.audio_filter.get("in").unwrap().source().failed_requests() > 0 {
println!("🎥 failed to put filter input frame"); println!("🎥 failed to put filter input frame");
} }
//let faplane: &[f32] = filtered_aframe.plane(0); //let faplane: &[f32] = filtered_aframe.plane(0);
//filtered_aframe.set_pts(Some(frame)); filtered_aframe.set_pts(Some(frame));
//filtered_aframe.set_pts(Some(frame));
self.audio_encoder.send_frame(&filtered_aframe).unwrap(); self.audio_encoder.send_frame(&filtered_aframe).unwrap();
self.receive_and_write_packets(EncoderToWriteFrom::Audio); self.receive_and_write_packets(EncoderToWriteFrom::Audio);
}, },
@ -429,7 +444,9 @@ impl retro::wrapper::Handler for MyEmulator {
return true; return true;
} }
self.video_encoder.set_frame_rate(system_av_info.timing.fps.into()); //self.video_encoder.set_frame_rate(system_av_info.timing.fps.into());
//self.video_encoder.set_time_base(Rational::new(1, 60));
//self.video_encoder.set_frame_rate(Some(Rational::new(1, 60)));
if system_av_info.timing.sample_rate.round() as i32 > 0 { if system_av_info.timing.sample_rate.round() as i32 > 0 {
self.audio_encoder.set_rate(system_av_info.timing.sample_rate.round() as i32); self.audio_encoder.set_rate(system_av_info.timing.sample_rate.round() as i32);
} }
@ -499,7 +516,7 @@ fn main() -> Fallible<()> {
emu.frame_properties_locked = true; emu.frame_properties_locked = true;
//for frame in 0..60*10 { //for frame in 0..60*10 {
for frame in 0..1300 { for frame in 0..800 {
eprintln!("🖼️ frame: {}", frame); eprintln!("🖼️ frame: {}", frame);
emu.run(frame); emu.run(frame);