From ea771c8dd7d51d4c63ebc16558b64e590371b25e Mon Sep 17 00:00:00 2001 From: Viv Lim Date: Mon, 26 Jul 2021 00:42:06 -0700 Subject: [PATCH] synced a/v on some players at least. ideally i'd like to write the header with the right time bases set. --- examples/ffmpeg_recorder.rs | 47 +++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/examples/ffmpeg_recorder.rs b/examples/ffmpeg_recorder.rs index 7770848..33cc495 100644 --- a/examples/ffmpeg_recorder.rs +++ b/examples/ffmpeg_recorder.rs @@ -82,7 +82,7 @@ fn audio_filter( ) -> Result { let mut afilter = filter::Graph::new(); 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); afilter.add(&filter::find("abuffer").unwrap(), "in", &args)?; //aresample? @@ -145,14 +145,16 @@ let wavname = Path::new("out.wav"); let acodec = ffmpeg::encoder::find(detected_acodec).unwrap().audio().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(); video_encoder.set_bit_rate(2560000); 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_output.set_time_base(Rational::new(1, fps_int)); - video_encoder.set_frame_rate(av_info.timing.fps.into()); + video_encoder.set_time_base(Rational::new(1, 60)); + video_encoder.set_frame_rate(Some(Rational::new(60, 1))); + + //video_encoder.set_frame_rate(av_info.timing.fps.into()); if av_info.geometry.base_height == 0 && av_info.geometry.base_width == 0 { 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_channel_layout(ChannelLayout::STEREO); 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_output.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, 60)); let mut audio_encoder = audio_encoder.open_as(acodec).unwrap(); //audio_output.set_parameters(&audio_encoder); @@ -250,8 +252,18 @@ static bool ffmpeg_init_config(struct ff_config_param *params, Ok(..) => { //if encoded_packet.size() > 0 { encoded_packet.set_stream(stream_index); - eprintln!("Writing packet, pts {:?} dts {:?} size {}", encoded_packet.pts(), encoded_packet.dts(), encoded_packet.size()); - match encoded_packet.write(&mut self.octx) { + eprintln!("📦 Writing packet, pts {:?} dts {:?} size {}", encoded_packet.pts(), encoded_packet.dts(), encoded_packet.size()); + 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"), Err(e) => eprintln!("Error writing: {}", e), } @@ -274,17 +286,19 @@ static bool ffmpeg_init_config(struct ff_config_param *params, 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(); loop { match self.video_filter.get("out").unwrap().sink().frame(&mut filtered_vframe) { 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 { 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.receive_and_write_packets(EncoderToWriteFrom::Video); @@ -312,20 +326,21 @@ static bool ffmpeg_init_config(struct ff_config_param *params, 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 {:?}", filtered_aframe); + 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)); + filtered_aframe.set_pts(Some(frame)); - //filtered_aframe.set_pts(Some(frame)); self.audio_encoder.send_frame(&filtered_aframe).unwrap(); self.receive_and_write_packets(EncoderToWriteFrom::Audio); }, @@ -429,7 +444,9 @@ impl retro::wrapper::Handler for MyEmulator { 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 { 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; //for frame in 0..60*10 { - for frame in 0..1300 { + for frame in 0..800 { eprintln!("🖼️ frame: {}", frame); emu.run(frame);