use adder_codec_core::codec::decoder::Decoder;
use adder_codec_core::codec::raw::stream::RawInput;
use adder_codec_core::D_ZERO_INTEGRATION;
use adder_codec_core::{SourceCamera, TimeMode};
use adder_codec_rs::framer::scale_intensity::event_to_intensity;
use adder_codec_rs::transcoder::source::video::show_display_force;
use bitstream_io::{BigEndian, BitReader};
use clap::Parser;
use ndarray::Array;
use opencv::core::{create_continuous, Mat, MatTraitManual, CV_64F, CV_64FC3};
use std::cmp::max;
use std::error::Error;
use std::fs::File;
use std::io::{BufReader, Write};
use std::{fmt, io};
use tokio::time::Instant;
#[derive(Parser, Debug, Default)]
#[clap(author, version, about, long_about = None)]
pub struct MyArgs {
#[clap(short, long)]
pub(crate) input: String,
#[clap(short = 'f', long, default_value_t = 60.0)]
pub playback_fps: f64,
}
#[derive(Debug)]
struct PlayerError(String);
impl fmt::Display for PlayerError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "There is an error: {}", self.0)
}
}
impl Error for PlayerError {}
#[allow(dead_code)]
fn main() -> Result<(), Box<dyn Error>> {
let args: MyArgs = MyArgs::parse();
let file_path = args.input.as_str();
let bufreader = BufReader::new(File::open(file_path)?);
let compression = RawInput::new();
let mut bitreader = BitReader::endian(bufreader, BigEndian);
let mut stream = Decoder::new_raw(compression, &mut bitreader).unwrap();
let meta = *stream.meta();
let header_bytes = stream.meta().header_size;
let first_event_position = stream.get_input_stream_position(&mut bitreader)?;
let eof_position_bytes = stream.get_eof_position(&mut bitreader)?;
let num_events = (eof_position_bytes - 1 - header_bytes as u64) / u64::from(meta.event_size);
let divisor = num_events / 100;
let frame_length = f64::from(meta.tps) / args.playback_fps;
let stdout = io::stdout();
let mut handle = io::BufWriter::new(stdout.lock());
let mut last_timestamps = Array::zeros((
stream.meta().plane.h_usize(),
stream.meta().plane.w_usize(),
stream.meta().plane.c_usize(),
));
let time_mode = stream.meta().time_mode;
stream.set_input_stream_position(&mut bitreader, first_event_position)?;
let mut display_mat = Mat::default();
match meta.plane.c() {
1 => {
create_continuous(
i32::from(meta.plane.h()),
i32::from(meta.plane.w()),
CV_64F,
&mut display_mat,
)?;
}
3 => {
create_continuous(
i32::from(meta.plane.h()),
i32::from(meta.plane.w()),
CV_64FC3,
&mut display_mat,
)?;
}
_ => {
return Err(Box::new(PlayerError("Bad number of channels".into())));
}
}
let mut event_count: u64 = 0;
let mut current_t = 0;
let mut frame_count: u128 = 1;
let mut last_frame_displayed_ts = Instant::now();
loop {
if event_count % divisor == 0 {
write!(
handle,
"\rPlaying back ADΔER file...{}%",
(event_count * 100) / num_events
)?;
handle.flush()?;
}
if u128::from(current_t) > (frame_count * frame_length as u128) {
let wait_time = max(
((1000.0 / args.playback_fps) as u128)
.saturating_sub((Instant::now() - last_frame_displayed_ts).as_millis()),
1,
) as i32;
show_display_force("ADΔER", &display_mat, wait_time)?;
last_frame_displayed_ts = Instant::now();
frame_count += 1;
}
match stream.digest_event(&mut bitreader) {
Ok(mut event) if event.d <= D_ZERO_INTEGRATION => {
event_count += 1;
let y = i32::from(event.coord.y);
let x = i32::from(event.coord.x);
let c = i32::from(event.coord.c.unwrap_or(0));
if time_mode == TimeMode::AbsoluteT {
if event.t > current_t {
current_t = event.t;
}
let dt = event.t - last_timestamps[[y as usize, x as usize, c as usize]];
last_timestamps[[y as usize, x as usize, c as usize]] = event.t;
if last_timestamps[[y as usize, x as usize, c as usize]]
% stream.meta().ref_interval
!= 0
{
last_timestamps[[y as usize, x as usize, c as usize]] = ((last_timestamps
[[y as usize, x as usize, c as usize]]
/ stream.meta().ref_interval)
+ 1)
* stream.meta().ref_interval;
}
event.t = dt;
} else {
last_timestamps[[y as usize, x as usize, c as usize]] += event.t;
if last_timestamps[[y as usize, x as usize, c as usize]]
% stream.meta().ref_interval
!= 0
{
last_timestamps[[y as usize, x as usize, c as usize]] = ((last_timestamps
[[y as usize, x as usize, c as usize]]
/ stream.meta().ref_interval)
+ 1)
* stream.meta().ref_interval;
}
if last_timestamps[[y as usize, x as usize, c as usize]] > current_t {
current_t = last_timestamps[[y as usize, x as usize, c as usize]];
}
}
let frame_intensity = (event_to_intensity(&event) * f64::from(meta.ref_interval))
/ match meta.source_camera {
SourceCamera::FramedU8 => f64::from(u8::MAX),
SourceCamera::FramedU16 => f64::from(u16::MAX),
SourceCamera::FramedU32 => f64::from(u32::MAX),
SourceCamera::FramedU64 => u64::MAX as f64,
SourceCamera::FramedF32 => {
todo!("Not yet implemented")
}
SourceCamera::FramedF64 => {
todo!("Not yet implemented")
}
SourceCamera::Dvs => f64::from(u8::MAX),
SourceCamera::DavisU8 => f64::from(u8::MAX),
SourceCamera::Atis => {
todo!("Not yet implemented")
}
SourceCamera::Asint => {
todo!("Not yet implemented")
}
};
unsafe {
let px: &mut f64 = display_mat.at_3d_unchecked_mut(y, x, c)?;
*px = frame_intensity;
}
}
Err(_e) => {
break;
}
_ => {}
}
}
Ok(())
}