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> {
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);