From 88d1ab0b0ed7452eac82d573171f276ea5e9a66f Mon Sep 17 00:00:00 2001 From: Vivian Lim Date: Thu, 22 Apr 2021 00:16:09 -0700 Subject: [PATCH] actually write a video!!!!! --- examples/ffmpeg_recorder.rs | 94 ++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/examples/ffmpeg_recorder.rs b/examples/ffmpeg_recorder.rs index 0d83ca8..88feba0 100644 --- a/examples/ffmpeg_recorder.rs +++ b/examples/ffmpeg_recorder.rs @@ -29,7 +29,7 @@ struct MyEmulator { audio_filter: filter::Graph, sys_path: Option, frame_properties_locked: bool, - //octx: ffmpeg::format::context::Output, + octx: ffmpeg::format::context::Output, } fn video_filter( @@ -125,27 +125,16 @@ impl MyEmulator { let vcodec = ffmpeg::encoder::find(detected_vcodec).unwrap().video().unwrap(); let acodec = ffmpeg::encoder::find(detected_acodec).unwrap().audio().unwrap(); - let mut audio_encoder = octx.add_stream(acodec).unwrap().codec().encoder().audio().unwrap(); - //let mut video_encoder = octx.add_stream(vcodec).unwrap().codec().encoder().video().unwrap(); let mut video_output = octx.add_stream(vcodec).unwrap(); let mut video_encoder = video_output.codec().encoder().video().unwrap(); - /* - let mut audio_output = octx.add_stream(acodec).unwrap(); - let mut audio_encoder = audio_output.codec().encoder().audio().unwrap(); - */ video_encoder.set_bit_rate(64000); video_encoder.set_format(video_encoder.codec().unwrap().video().unwrap().formats().unwrap().nth(0).unwrap()); - audio_encoder.set_bit_rate(64000); - audio_encoder.set_rate(44100); - audio_encoder.set_format(audio_encoder.codec().unwrap().audio().unwrap().formats().unwrap().nth(0).unwrap()); - audio_encoder.set_channels(2); - audio_encoder.set_channel_layout(ChannelLayout::STEREO); - 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()); + if av_info.geometry.base_height == 0 && av_info.geometry.base_width == 0 { av_info.geometry.base_width = 320; av_info.geometry.base_height = 224; @@ -158,18 +147,42 @@ impl MyEmulator { video_encoder.set_height(av_info.geometry.base_height); //video_encoder.set_aspect_ratio(av_info.geometry.aspect_ratio as f64); - audio_encoder.set_rate(44100); - let pix_fmt = PixelFormat::ARGB1555; // temporary until env call is made let video_filter = video_filter(&video_encoder, &av_info, pix_fmt).unwrap(); - let audio_filter = audio_filter(&audio_encoder, av_info.timing.sample_rate).unwrap(); let video_encoder = video_encoder.open_as(vcodec).unwrap(); video_output.set_parameters(&video_encoder); + + let mut audio_output = octx.add_stream(acodec).unwrap(); + let mut audio_encoder = audio_output.codec().encoder().audio().unwrap(); + + //let mut video_encoder = octx.add_stream(vcodec).unwrap().codec().encoder().video().unwrap(); + /* + let mut audio_output = octx.add_stream(acodec).unwrap(); + let mut audio_encoder = audio_output.codec().encoder().audio().unwrap(); + */ + /* + retroarch inits +static bool ffmpeg_init_config(struct ff_config_param *params, + if (!ffmpeg_init_muxer_pre(handle)) + if (!ffmpeg_init_video(handle)) + av_frame_alloc + */ + + + audio_encoder.set_bit_rate(64000); + audio_encoder.set_rate(44100); + audio_encoder.set_format(audio_encoder.codec().unwrap().audio().unwrap().formats().unwrap().nth(0).unwrap()); + audio_encoder.set_channels(2); + audio_encoder.set_channel_layout(ChannelLayout::STEREO); + + audio_encoder.set_rate(44100); + let audio_filter = audio_filter(&audio_encoder, av_info.timing.sample_rate).unwrap(); + let mut audio_encoder = audio_encoder.open_as(acodec).unwrap(); audio_encoder.set_rate(av_info.timing.sample_rate.round() as i32); //audio_output.set_parameters(&audio_encoder); - +octx.write_header().unwrap(); let emu = MyEmulator { retro, sys_info, @@ -183,7 +196,7 @@ impl MyEmulator { audio_filter, sys_path: sys_path.as_ref().map(|x| x.as_ref().to_path_buf()), frame_properties_locked: false, - //octx, // AAA + octx, }; let mut pin_emu = Box::pin(emu); @@ -207,17 +220,28 @@ impl MyEmulator { aplane.copy_from_slice(self.audio_buf.as_ref()); self.audio_buf.clear(); + //vframe.set_pts(Some(frame)); + unsafe + { + //(*vframe.as_mut_ptr()).pts = frame; + //(*vframe.as_mut_ptr()).pkt_dts = frame; + } + let mut out = ffmpeg::Packet::empty(); self.video_filter.get("in").unwrap().source().add(&vframe).unwrap(); self.audio_filter.get("in").unwrap().source().add(&aframe).unwrap(); let mut filtered_vframe = frame::Video::empty(); + + // ffmpeg_push_video_thread takes ffmpeg_t handle which is a retroarch struct holding ffmpeg context + // video_frame_record_scale + // grabs frame from input (record_video_data struct) and copies it to ffmpeg_t handle .video.conv_frame.data[0] + // conv_frame is an AVFrame. where's that from while self.video_filter.get("out").unwrap().sink().frame(&mut filtered_vframe).is_ok() { if self.video_filter.get("in").unwrap().source().failed_requests() > 0 { println!("🎥 failed to put filter input frame"); } - vframe.set_pts(Some(frame)); let encode_result = self.video_encoder.send_frame(&filtered_vframe).unwrap(); - eprintln!("encoded: {:?}", encode_result); + //eprintln!("encoded: {:?}", encode_result); /*if encode_result { out.set_stream(0); out.write_interleaved(octx).unwrap(); @@ -225,9 +249,19 @@ impl MyEmulator { */ let mut encoded_packet = ffmpeg::Packet::empty(); - while self.video_encoder.receive_packet(&mut encoded_packet).is_ok() { + while let Ok(..) = self.video_encoder.receive_packet(&mut encoded_packet) { //eprintln!("Attempting write: {:?}", encoded_packet); - encoded_packet.set_stream(0); // use stream index... + //encoded_packet.set_stream(0); // use stream index... + + unsafe { + (*self.octx.as_mut_ptr()).debug = 1; + eprintln!("oformat: {:?}", &((*self.octx.as_mut_ptr()).oformat)); + eprintln!("flags: {:?}", (*(*self.octx.as_mut_ptr()).oformat).flags); + } + + if encoded_packet.size() > 0 { + encoded_packet.write(&mut self.octx).unwrap(); // AAA + } //encoded_packet.rescale_ts(Rational(1, 1), self.time_base); //encoded_packet.write_interleaved(&mut self.octx).unwrap(); // AAA } @@ -270,11 +304,9 @@ impl retro::wrapper::Handler for MyEmulator { let pitch = pitch as usize; let vplane = vframe.data_mut(0); - /* sus if data.len() == vplane.len() && pitch == stride { vplane.copy_from_slice(&data); } else { - */ for y in 0..(height as usize) { let ffbegin = y * stride; let lrbegin = y * pitch; @@ -283,7 +315,9 @@ impl retro::wrapper::Handler for MyEmulator { &data[lrbegin..(lrbegin + min)] ); } - //} + } + + //vframe.set_pts(Some(69)); self.video_frames.push_back(vframe); } @@ -382,15 +416,21 @@ fn main() -> Fallible<()> { ffmpeg::init().unwrap(); let mut octx = format::output(&opt.video)?; + unsafe { + (*octx.as_mut_ptr()).debug = 1; + eprintln!("oformat: {:?}", &((*octx.as_mut_ptr()).oformat)); + eprintln!("flags: {:?}", (*(*octx.as_mut_ptr()).oformat).flags); + } + + //octx.write_header().unwrap(); let mut emu = MyEmulator::new(opt.core, &opt.system, &opt.video, octx); emu.load_game(opt.rom); emu.frame_properties_locked = true; - //octx.write_header().unwrap(); //for frame in 0..60*10 { - for frame in 0..120 { + for frame in 0..9200 { eprintln!("🖼️ frame: {}", frame); emu.run(frame);