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