1use crate::framer::scale_intensity::{FrameValue, SaeTime};
2use crate::transcoder::source::video::FramedViewMode::SAE;
3use crate::transcoder::source::video::{
4 integrate_for_px, Source, SourceError, Video, VideoBuilder,
5};
6use crate::utils::cv::{clamp_u8, mid_clamp_u8};
7use crate::utils::viz::ShowFeatureMode;
8use adder_codec_core::codec::{EncoderOptions, EncoderType};
9use adder_codec_core::Mode::Continuous;
10use adder_codec_core::{
11 DeltaT, Event, PixelMultiMode, PlaneSize, SourceCamera, SourceType, TimeMode,
12};
13use ndarray::Array3;
14use rayon::ThreadPool;
15use serde::{Deserialize, Serialize};
16use std::error::Error;
17use std::fs::File;
18use std::io::{self, BufRead, BufReader, Read, Seek, SeekFrom, Write};
19use std::path::PathBuf;
20use std::str::FromStr;
21use tokio::runtime::Runtime;
22use video_rs_adder_dep::Frame;
23
24const PROPHESEE_SOURCE_TPS: u32 = 1000000;
26
27pub struct Prophesee<W: Write + std::marker::Send + std::marker::Sync + 'static> {
29 pub(crate) video: Video<W>,
30
31 input_reader: BufReader<File>,
32
33 running_t: u32,
34
35 t_subtract: u32,
36
37 pub dvs_last_timestamps: Array3<u32>,
39
40 pub dvs_last_ln_val: Array3<f64>,
42
43 camera_theta: f64,
44}
45
46#[derive(Debug, Serialize, Deserialize, Clone)]
48pub struct DvsEvent {
49 t: u32,
50 x: u16,
51 y: u16,
52 p: u8,
53}
54
55unsafe impl<W: Write + std::marker::Send + std::marker::Sync + 'static> Sync for Prophesee<W> {}
56
57impl<W: Write + std::marker::Send + std::marker::Sync + 'static> Prophesee<W> {
58 pub fn new(ref_time: u32, input_filename: String) -> Result<Self, Box<dyn Error>> {
60 let source = File::open(PathBuf::from(input_filename))?;
61 let mut input_reader = BufReader::new(source);
62
63 let (_, _, _, size) = parse_header(&mut input_reader).unwrap();
65
66 let plane = PlaneSize::new(size.1 as u16, size.0 as u16, 1)?;
67
68 let mut video = Video::new(plane, Continuous, None)?
69 .chunk_rows(1)
70 .time_parameters(
75 ref_time * PROPHESEE_SOURCE_TPS,
76 ref_time,
77 ref_time * 2,
78 Some(TimeMode::AbsoluteT),
79 )?;
80
81 let start_intensities = vec![128_u8; video.state.plane.volume()];
82 video.state.running_intensities = Array3::from_shape_vec(
83 (plane.h().into(), plane.w().into(), plane.c().into()),
84 start_intensities,
85 )?;
86 video.display_frame_features = video.state.running_intensities.clone();
87
88 let timestamps = vec![2_u32; video.state.plane.volume()];
89
90 let dvs_last_timestamps: Array3<u32> = Array3::from_shape_vec(
91 (plane.h().into(), plane.w().into(), plane.c().into()),
92 timestamps,
93 )?;
94
95 let plane = &video.state.plane;
96
97 let start_vals = vec![(128.0_f64 / 255.0_f64).ln_1p(); video.state.plane.volume()];
98
99 let dvs_last_ln_val: Array3<f64> = Array3::from_shape_vec(
100 (plane.h() as usize, plane.w() as usize, plane.c() as usize),
101 start_vals,
102 )?;
103
104 let prophesee_source = Prophesee {
105 video,
106 input_reader,
107 running_t: 0,
108 t_subtract: 0,
109 dvs_last_timestamps,
110 dvs_last_ln_val,
111 camera_theta: 0.02, };
113
114 Ok(prophesee_source)
115 }
116}
117
118impl<W: Write + std::marker::Send + std::marker::Sync + 'static> Source<W> for Prophesee<W> {
119 fn consume(&mut self) -> Result<Vec<Vec<Event>>, SourceError> {
120 if self.running_t == 0 {
121 self.video.integrate_matrix(
122 self.video.state.running_intensities.clone(),
123 self.video.state.params.ref_time as f32,
124 )?;
125 let first_events: Vec<Event> = self
126 .video
127 .integrate_matrix(
128 self.video.state.running_intensities.clone(),
129 self.video.state.params.ref_time as f32,
130 )?
131 .into_iter()
132 .flatten()
133 .collect();
134 assert_eq!(first_events.len(), self.video.state.plane.volume());
135 self.running_t = 2;
136 }
137
138 let view_interval = PROPHESEE_SOURCE_TPS / 60;
140
141 let mut dvs_events: Vec<DvsEvent> = Vec::new();
144 let mut dvs_event;
145 let start_running_t = self.running_t;
146 loop {
147 dvs_event = match decode_event(&mut self.input_reader) {
150 Ok(mut dvs_event) => {
151 dvs_event.t -= self.t_subtract;
157
158 if dvs_event.t > self.running_t {
159 self.running_t = dvs_event.t;
160 }
161 dvs_event
162 }
163 Err(e) => {
164 dbg!("End of input file");
165 end_events(self);
166 return Err(e.into());
167 }
168 };
169 dvs_events.push(dvs_event);
170 if dvs_events.last().unwrap().t > start_running_t + view_interval {
171 break;
172 }
173 }
174
175 let mut events: Vec<Event> = Vec::new();
176 let crf_parameters = *self.video.encoder.options.crf.get_parameters();
177
178 for dvs_event in dvs_events {
181 let x = dvs_event.x as usize;
182 let y = dvs_event.y as usize;
183 let p = dvs_event.p as usize;
184 let t = dvs_event.t;
185
186 let last_t = self.dvs_last_timestamps[[y, x, 0]];
188
189 if t < last_t {
190 continue;
192 }
193
194 let mut last_ln_val = self.dvs_last_ln_val[[y, x, 0]];
196
197 let px = &mut self.video.event_pixel_trees[[y, x, 0]];
198
199 if t > last_t + 1 {
200 let mut last_val = (last_ln_val.exp() - 1.0) * 255.0;
202
203 mid_clamp_u8(&mut last_val, &mut last_ln_val);
204
205 let time_spanned = (t - last_t - 1) * self.video.state.params.ref_time;
207 let intensity_to_integrate = last_val * (t - last_t - 1) as f64;
208
209 let mut base_val = 0;
210 let _ = integrate_for_px(
211 px,
212 &mut base_val,
213 last_val as u8,
214 intensity_to_integrate as f32,
215 time_spanned as f32,
216 &mut events,
217 &self.video.state.params,
218 &crf_parameters,
219 );
220 }
221
222 let mut new_ln_val = match p {
224 0 => last_ln_val - self.camera_theta,
225 1 => last_ln_val + self.camera_theta,
226 _ => panic!("Invalid polarity"),
227 };
228
229 self.dvs_last_ln_val[[y, x, 0]] = new_ln_val;
231
232 self.dvs_last_timestamps[[y, x, 0]] = t;
234
235 if t > last_t {
236 let mut new_val = (new_ln_val.exp() - 1.0) * 255.0;
237
238 mid_clamp_u8(&mut new_val, &mut new_ln_val);
239
240 self.dvs_last_ln_val[[y, x, 0]] = new_ln_val;
242
243 let time_spanned = self.video.state.params.ref_time;
245 let intensity_to_integrate = new_val;
246
247 let mut base_val = 0;
248 let _ = integrate_for_px(
249 px,
250 &mut base_val,
251 new_val as u8,
252 intensity_to_integrate as f32,
253 time_spanned as f32,
254 &mut events,
255 &self.video.state.params,
256 &crf_parameters,
257 );
258 }
259
260 if let Some(event) = px.arena[0].best_event {
262 self.video.state.running_intensities[[y, x, 0]] = u8::get_frame_value(
263 &event.into(),
264 SourceType::U8,
265 self.video.state.params.ref_time as f64,
266 32.0,
267 self.video.state.params.delta_t_max,
268 self.video.instantaneous_view_mode,
269 if self.video.instantaneous_view_mode == SAE {
270 Some(SaeTime {
271 running_t: px.running_t as DeltaT,
272 last_fired_t: px.last_fired_t as DeltaT,
273 })
274 } else {
275 None
276 },
277 );
278 self.video.display_frame_features[[y, x, 0]] =
279 self.video.state.running_intensities[[y, x, 0]];
280 };
281 }
282
283 if self.video.state.feature_detection {
284 self.video.display_frame_features = self.video.state.running_intensities.clone();
285 }
286
287 let events_nested: Vec<Vec<Event>> = vec![events];
290
291 self.video.handle_features(&events_nested)?;
292
293 for events in &events_nested {
294 for event in events {
295 self.video.encoder.ingest_event(*event)?;
296 }
297 }
298
299 Ok(events_nested)
300 }
301
302 fn crf(&mut self, crf: u8) {
303 self.video.update_crf(crf);
304 }
305
306 fn get_video_mut(&mut self) -> &mut Video<W> {
307 &mut self.video
308 }
309
310 fn get_video_ref(&self) -> &Video<W> {
311 &self.video
312 }
313
314 fn get_video(self) -> Video<W> {
315 self.video
316 }
317
318 fn get_input(&self) -> Option<&Frame> {
319 None
320 }
321
322 fn get_running_input_bitrate(&self) -> f64 {
323 0.0
325 }
326}
327
328fn end_events<W: Write + std::marker::Send + std::marker::Sync + 'static>(
329 prophesee: &mut Prophesee<W>,
330) {
331 let mut events: Vec<Event> = Vec::new();
332 let crf_parameters = *prophesee.video.encoder.options.crf.get_parameters();
333
334 for y in 0..prophesee.video.state.plane.h_usize() {
335 for x in 0..prophesee.video.state.plane.w_usize() {
336 let px = &mut prophesee.video.event_pixel_trees[[y, x, 0]];
337 let mut base_val = 0;
338
339 let last_ln_val = prophesee.dvs_last_ln_val[[y, x, 0]];
341
342 let last_val = (last_ln_val.exp() - 1.0) * 255.0;
344
345 assert!(prophesee.running_t - prophesee.dvs_last_timestamps[[y, x, 0]] > 0);
346
347 let time_spanned = (prophesee.running_t - prophesee.dvs_last_timestamps[[y, x, 0]])
349 * prophesee.video.state.params.ref_time;
350 let intensity_to_integrate = last_val * time_spanned as f64;
351
352 let _ = integrate_for_px(
353 px,
354 &mut base_val,
355 last_val as u8,
356 intensity_to_integrate as f32,
357 time_spanned as f32,
358 &mut events,
359 &prophesee.video.state.params,
360 &crf_parameters,
361 );
362 }
363 }
364
365 for event in &events {
366 prophesee.video.encoder.ingest_event(*event).unwrap();
367 }
368}
369
370fn parse_header(file: &mut BufReader<File>) -> io::Result<(u64, u8, u8, (u32, u32))> {
371 file.seek(SeekFrom::Start(0))?; let mut bod = 0;
373 let mut end_of_header = false;
374 let mut num_comment_line = 0;
375 let mut size = [None, None];
376
377 while !end_of_header {
379 bod = file.seek(SeekFrom::Current(0))?; let mut line = Vec::new(); file.read_until(b'\n', &mut line)?; if line.is_empty() || line[0] != b'%' {
383 end_of_header = true;
384 } else {
385 let words: Vec<&[u8]> = line.split(|&x| x == b' ' || x == b'\t').collect(); if words.len() > 1 {
388 match words[1] {
389 b"Height" => {
390 size[0] = line_to_hw(words);
391 }
392 b"Width" => {
393 size[1] = line_to_hw(words);
394 }
395 _ => {}
396 }
397 }
398 num_comment_line += 1;
399 }
400 }
401
402 file.seek(SeekFrom::Start(bod))?; let (ev_type, ev_size) = if num_comment_line > 0 {
405 let mut buf = [0; 2]; file.read_exact(&mut buf)?;
408 let ev_type = buf[0];
409 let ev_size = buf[1];
410 if ev_size != 8 || (ev_type != 0 && ev_type != 12) {
411 panic!("Invalid Prophesee event size");
412 }
413
414 (ev_type, ev_size)
415 } else {
416 (0, 0) };
418 bod = file.seek(SeekFrom::Current(0))?;
419 Ok((
420 bod,
421 ev_type,
422 ev_size,
423 (size[0].unwrap_or(70), size[1].unwrap_or(100)),
424 ))
425}
426
427fn line_to_hw(words: Vec<&[u8]>) -> Option<u32> {
428 let word = words.get(2).unwrap();
429 let mut new_word = *word;
430 if *word.last().unwrap() == '\n' as u8 {
431 new_word = &word[..word.len() - 1];
433 }
434 std::str::from_utf8(new_word)
435 .ok()
436 .and_then(|s| s.parse().ok())
437}
438
439fn decode_event(reader: &mut BufReader<File>) -> io::Result<DvsEvent> {
440 let mut buffer = [0; 8]; reader.read_exact(&mut buffer)?;
443
444 let t = u32::from_le_bytes([buffer[0], buffer[1], buffer[2], buffer[3]]);
446 let data = i32::from_le_bytes([buffer[4], buffer[5], buffer[6], buffer[7]]);
447
448 let x = (data & 0x3FF) as u16; let y = ((data & 0xFFFC000) >> 14) as u16; let p = ((data & 0x10000000) >> 28) as u8; Ok(DvsEvent { t, x, y, p })
454}
455
456impl<W: Write + std::marker::Send + std::marker::Sync + 'static> VideoBuilder<W> for Prophesee<W> {
457 fn crf(mut self, crf: u8) -> Self {
458 self.video.update_crf(crf);
459 self
460 }
461
462 fn quality_manual(
463 mut self,
464 c_thresh_baseline: u8,
465 c_thresh_max: u8,
466 delta_t_max_multiplier: u32,
467 c_increase_velocity: u8,
468 feature_c_radius_denom: f32,
469 ) -> Self {
470 self.video.update_quality_manual(
471 c_thresh_baseline,
472 c_thresh_max,
473 delta_t_max_multiplier,
474 c_increase_velocity,
475 feature_c_radius_denom,
476 );
477 self
478 }
479
480 fn chunk_rows(mut self, chunk_rows: usize) -> Self {
481 self.video = self.video.chunk_rows(chunk_rows);
482 self
483 }
484
485 fn time_parameters(
486 mut self,
487 tps: DeltaT,
488 ref_time: DeltaT,
489 delta_t_max: DeltaT,
490 time_mode: Option<TimeMode>,
491 ) -> Result<Self, SourceError> {
492 eprintln!("setting dtref to {}", ref_time);
493 self.video = self
494 .video
495 .time_parameters(tps, ref_time, delta_t_max, time_mode)?;
496 Ok(self)
497 }
498
499 fn write_out(
500 mut self,
501 source_camera: SourceCamera,
502 time_mode: TimeMode,
503 pixel_multi_mode: PixelMultiMode,
504 adu_interval: Option<usize>,
505 encoder_type: EncoderType,
506 encoder_options: EncoderOptions,
507 write: W,
508 ) -> Result<Box<Self>, SourceError> {
509 self.video = self.video.write_out(
510 Some(source_camera),
511 Some(time_mode),
512 Some(pixel_multi_mode),
513 adu_interval,
514 encoder_type,
515 encoder_options,
516 write,
517 )?;
518 Ok(Box::new(self))
519 }
520 fn detect_features(mut self, detect_features: bool, show_features: ShowFeatureMode) -> Self {
521 self.video = self.video.detect_features(detect_features, show_features);
522 self
523 }
524
525 #[cfg(feature = "feature-logging")]
526 fn log_path(self, _name: String) -> Self {
527 todo!()
528 }
529}