adder_codec_rs/utils/
stream_migration.rs

1use adder_codec_core::codec::decoder::Decoder;
2use adder_codec_core::codec::encoder::Encoder;
3use adder_codec_core::{DeltaT, Event, SourceCamera, TimeMode};
4use bitstream_io::BigEndian;
5use ndarray::Array3;
6use std::error::Error;
7use std::io::{Read, Seek, Write};
8
9/// Transforms an [`Event`] with an [absolute](TimeMode::AbsoluteT) timestamp to am [`Event`] with
10/// a [delta](TimeMode::DeltaT) timestamp.
11///
12/// # Arguments
13///
14/// * `event`: [`Event`] to be transformed
15/// * `last_t`: last [absolute](TimeMode::AbsoluteT) timestamp of the pixel
16///
17/// returns: transformed Event
18pub fn absolute_event_to_dt_event(mut event: Event, last_t: DeltaT) -> Event {
19    event.t -= last_t;
20    event
21}
22
23/// Transforms an input stream to a new output stream with v2 of the codec.
24///
25/// # Arguments
26///
27/// * `input_stream`: input stream to be migrated
28/// * `bitreader`: bitreader to be used for reading the input stream
29/// * `output_stream`: output stream to be written to
30///
31/// returns: `Result<Encoder<W>, Box<dyn Error, Global>>` where `W` is the type of the output stream
32pub fn migrate_v2<W: Write + std::marker::Send + std::marker::Sync + 'static, R: Read + Seek>(
33    mut input_stream: Decoder<R>,
34    bitreader: &mut bitstream_io::BitReader<R, BigEndian>,
35    mut output_stream: Encoder<W>,
36) -> Result<Encoder<W>, Box<dyn Error>> {
37    let mut t_tree: Array3<u32> = Array3::from_shape_vec(
38        (
39            input_stream.meta().plane.h_usize(),
40            input_stream.meta().plane.w_usize(),
41            input_stream.meta().plane.c_usize(),
42        ),
43        vec![0_u32; input_stream.meta().plane.volume()],
44    )?;
45
46    loop {
47        let mut event = match input_stream.digest_event(bitreader) {
48            Ok(event) => event,
49            Err(_) => {
50                break;
51            }
52        };
53        let t = &mut t_tree[[
54            event.coord.y_usize(),
55            event.coord.x_usize(),
56            event.coord.c_usize(),
57        ]];
58
59        *t += event.t;
60
61        if output_stream.meta().time_mode == TimeMode::AbsoluteT {
62            event.t = *t;
63
64            // If framed video source, we can take advantage of scheme that reduces event rate by half
65            if input_stream.meta().codec_version > 0
66                && match input_stream.meta().source_camera {
67                    SourceCamera::FramedU8
68                    | SourceCamera::FramedU16
69                    | SourceCamera::FramedU32
70                    | SourceCamera::FramedU64
71                    | SourceCamera::FramedF32
72                    | SourceCamera::FramedF64 => true,
73                    SourceCamera::Dvs
74                    | SourceCamera::DavisU8
75                    | SourceCamera::Atis
76                    | SourceCamera::Asint => false,
77                }
78                && *t % input_stream.meta().ref_interval > 0
79            {
80                *t = ((*t / input_stream.meta().ref_interval) + 1)
81                    * input_stream.meta().ref_interval;
82            }
83        }
84
85        output_stream.ingest_event(event)?;
86    }
87    Ok(output_stream)
88}
89
90#[cfg(test)]
91mod tests {
92    use crate::framer::driver::FramerMode::INSTANTANEOUS;
93    use crate::framer::driver::{FrameSequence, Framer, FramerBuilder};
94    use crate::utils::stream_migration::absolute_event_to_dt_event;
95    use adder_codec_core::codec::decoder::Decoder;
96    use adder_codec_core::codec::encoder::Encoder;
97    use adder_codec_core::codec::raw::stream::{RawInput, RawOutput};
98    use adder_codec_core::codec::{CodecMetadata, EncoderOptions};
99    use adder_codec_core::SourceCamera::FramedU8;
100    use adder_codec_core::TimeMode::AbsoluteT;
101    use adder_codec_core::{Coord, Event, PlaneSize, TimeMode};
102    use bitstream_io::{BigEndian, BitReader};
103    use ndarray::Array3;
104    use std::fs::File;
105    use std::io::{BufReader, BufWriter, Cursor};
106
107    /// Test the `migrate_v2` function by making a v1 stream, converting it to v2, and checking the
108    /// events
109    #[test]
110    fn test_migrate_v2() -> Result<(), Box<dyn std::error::Error>> {
111        use crate::utils::stream_migration::migrate_v2;
112
113        let plane = PlaneSize::new(1, 1, 1).unwrap();
114
115        let output = Vec::new();
116        let bufwriter = BufWriter::new(output);
117        let compression = RawOutput::new(
118            CodecMetadata {
119                codec_version: 1, // Make this a v1 stream
120                header_size: 0,
121                time_mode: TimeMode::DeltaT,
122                plane,
123                tps: 255 * 30,
124                ref_interval: 255,
125                delta_t_max: 2550,
126                event_size: 0,
127                source_camera: FramedU8,
128                adu_interval: 1,
129            },
130            bufwriter,
131        );
132        let mut stream = Encoder::new_raw(compression, EncoderOptions::default(plane));
133
134        // Encode the events
135        let event: Event = Event {
136            coord: Coord {
137                x: 0,
138                y: 0,
139                c: None,
140            },
141            d: 5,
142            t: 600,
143        };
144        stream.ingest_event(event)?;
145        stream.ingest_event(event)?;
146        stream.ingest_event(event)?;
147        let event: Event = Event {
148            coord: Coord {
149                x: 0,
150                y: 0,
151                c: None,
152            },
153            d: 5,
154            t: 123,
155        };
156        stream.ingest_event(event)?;
157
158        let writer = stream.close_writer().unwrap().unwrap();
159        let bytes = writer.into_inner().unwrap();
160        let tmp = Cursor::new(&*bytes);
161        let bufreader = BufReader::new(tmp);
162        let compression = RawInput::new();
163        let mut bitreader = BitReader::endian(bufreader, BigEndian);
164        let reader = Decoder::new_raw(compression, &mut bitreader).unwrap();
165
166        let output = Vec::new();
167        let bufwriter = BufWriter::new(output);
168        let compression = RawOutput::new(
169            CodecMetadata {
170                codec_version: 2, // Make this a v1 stream
171                header_size: 0,
172                time_mode: TimeMode::AbsoluteT,
173                plane,
174                tps: 255 * 30,
175                ref_interval: 255,
176                delta_t_max: 2550,
177                event_size: 0,
178                source_camera: FramedU8,
179                adu_interval: 1,
180            },
181            bufwriter,
182        );
183        let mut stream = Encoder::new_raw(compression, EncoderOptions::default(plane));
184
185        stream = migrate_v2(reader, &mut bitreader, stream)?;
186
187        let writer = stream.close_writer().unwrap().unwrap();
188        let bytes = writer.into_inner().unwrap();
189        let tmp = Cursor::new(&*bytes);
190        let bufreader = BufReader::new(tmp);
191        let compression = RawInput::new();
192        let mut bitreader = BitReader::endian(bufreader, BigEndian);
193        let mut reader = Decoder::new_raw(compression, &mut bitreader).unwrap();
194
195        /*
196        Now, the events when converted to v2 with absolute_t mode should have these t values:
197            600, 1365, 2130, 2418
198         */
199        let mut event = reader.digest_event(&mut bitreader)?;
200        assert_eq!(event.coord.x as i32, 0);
201        assert_eq!(event.coord.y as i32, 0);
202        assert_eq!(event.coord.c, None);
203        let dt = event.t;
204        assert_eq!(dt, 600);
205        assert_eq!(event.d, 5);
206
207        event = reader.digest_event(&mut bitreader)?;
208        let dt = event.t;
209        assert_eq!(dt, 1365);
210        event = reader.digest_event(&mut bitreader)?;
211        let dt = event.t;
212        assert_eq!(dt, 2130);
213        event = reader.digest_event(&mut bitreader)?;
214        let dt = event.t;
215        assert_eq!(dt, 2418);
216
217        Ok(())
218    }
219
220    /// Test the `migrate_v2` function by making a v1 stream, converting it to v2, and checking the
221    /// events
222    #[test]
223    fn test_migrate_v2_nyc() -> Result<(), Box<dyn std::error::Error>> {
224        use crate::utils::stream_migration::migrate_v2;
225
226        let bufreader = BufReader::new(File::open("./tests/samples/nyc_v1_1px.adder")?);
227        let compression = RawInput::new();
228        let mut bitreader = BitReader::endian(bufreader, BigEndian);
229        let reader = Decoder::new_raw(compression, &mut bitreader).unwrap();
230
231        let output = Vec::new();
232        let bufwriter = BufWriter::new(output);
233        let mut meta = *reader.meta();
234        meta.codec_version = 2;
235        meta.time_mode = AbsoluteT;
236        let compression = RawOutput::new(meta, bufwriter);
237        let mut stream = Encoder::new_raw(compression, EncoderOptions::default(meta.plane));
238
239        stream = migrate_v2(reader, &mut bitreader, stream)?;
240
241        let writer = stream.close_writer().unwrap().unwrap();
242        let bytes = writer.into_inner().unwrap();
243        let tmp = Cursor::new(&*bytes);
244        let bufreader = BufReader::new(tmp);
245        let compression = RawInput::new();
246        let mut bitreader_migrate = BitReader::endian(bufreader, BigEndian);
247        let mut reader_migrate = Decoder::new_raw(compression, &mut bitreader_migrate).unwrap();
248
249        let bufreader = BufReader::new(File::open("./tests/samples/nyc_source_v2_2_1px.adder")?);
250        let compression = RawInput::new();
251        let mut bitreader_gt = BitReader::endian(bufreader, BigEndian);
252        let mut reader_gt = Decoder::new_raw(compression, &mut bitreader_gt).unwrap();
253
254        let mut event_count = 0;
255        loop {
256            let event_migrate = match reader_migrate.digest_event(&mut bitreader_migrate) {
257                Ok(ev) => ev,
258                Err(_) => {
259                    break;
260                }
261            };
262            let event_gt = match reader_gt.digest_event(&mut bitreader_gt) {
263                Ok(ev) => ev,
264                Err(_) => {
265                    break;
266                }
267            };
268            event_count += 1;
269            assert_eq!(event_migrate.coord.x as i32, event_gt.coord.x as i32);
270            assert_eq!(event_migrate.coord.y as i32, event_gt.coord.y as i32);
271            assert_eq!(event_migrate.coord.c, event_gt.coord.c);
272            let dt = event_migrate.t;
273            let dt_g = event_gt.t;
274            assert_eq!(dt, dt_g);
275            assert_eq!(event_migrate.d, event_gt.d);
276        }
277        assert_eq!(event_count, 5);
278
279        Ok(())
280    }
281
282    /// Test that when reconstructing framed video, we get the same results with both `DeltaT` and
283    /// `AbsoluteT` time modes
284    #[test]
285    fn test_migrate_v2_bunny_1px() -> Result<(), Box<dyn std::error::Error>> {
286        let bufreader = BufReader::new(File::open("./tests/samples/bunny_v2_t.adder")?);
287        let compression = RawInput::new();
288        let mut bitreader_t = BitReader::endian(bufreader, BigEndian);
289        let mut input_stream_t = Decoder::new_raw(compression, &mut bitreader_t).unwrap();
290
291        let reconstructed_frame_rate = 30.0;
292
293        let mut frame_sequence_t: FrameSequence<u8> =
294            FramerBuilder::new(input_stream_t.meta().plane, 64)
295                .codec_version(input_stream_t.meta().codec_version, TimeMode::AbsoluteT)
296                .time_parameters(
297                    input_stream_t.meta().tps,
298                    input_stream_t.meta().ref_interval,
299                    input_stream_t.meta().delta_t_max,
300                    Some(reconstructed_frame_rate),
301                )
302                .mode(INSTANTANEOUS)
303                .source(
304                    input_stream_t.get_source_type(),
305                    input_stream_t.meta().source_camera,
306                )
307                .finish();
308
309        let bufreader = BufReader::new(File::open("./tests/samples/bunny_v2_dt.adder")?);
310        let compression = RawInput::new();
311        let mut bitreader_dt = BitReader::endian(bufreader, BigEndian);
312        let mut input_stream_dt = Decoder::new_raw(compression, &mut bitreader_dt).unwrap();
313
314        let mut frame_sequence_dt: FrameSequence<u8> =
315            FramerBuilder::new(input_stream_dt.meta().plane, 64)
316                .codec_version(input_stream_dt.meta().codec_version, TimeMode::DeltaT)
317                .time_parameters(
318                    input_stream_dt.meta().tps,
319                    input_stream_dt.meta().ref_interval,
320                    input_stream_dt.meta().delta_t_max,
321                    Some(reconstructed_frame_rate),
322                )
323                .mode(INSTANTANEOUS)
324                .source(
325                    input_stream_dt.get_source_type(),
326                    input_stream_dt.meta().source_camera,
327                )
328                .finish();
329
330        let mut event_count = 0;
331        let mut last_t = 0;
332        let mut t_frame: Option<Vec<Array3<Option<u8>>>> = None;
333        let mut dt_frame;
334        loop {
335            let event_t = match input_stream_t.digest_event(&mut bitreader_t) {
336                Ok(ev) => ev,
337                Err(_) => {
338                    break;
339                }
340            };
341            if frame_sequence_t.ingest_event(&mut event_t.clone(), None) {
342                t_frame = frame_sequence_t.pop_next_frame();
343            }
344
345            let event_dt = match input_stream_dt.digest_event(&mut bitreader_dt) {
346                Ok(ev) => ev,
347                Err(_) => {
348                    break;
349                }
350            };
351            if frame_sequence_dt.ingest_event(&mut event_dt.clone(), None) {
352                dt_frame = frame_sequence_dt.pop_next_frame();
353
354                let dt_val = dt_frame.unwrap()[0][[0, 0, 0]].unwrap();
355                let t_val = t_frame.clone().unwrap()[0][[0, 0, 0]].unwrap();
356                assert_eq!(dt_val, t_val);
357            }
358
359            event_count += 1;
360
361            let event_t_dt = absolute_event_to_dt_event(event_t, last_t);
362            last_t = event_t.t;
363
364            // We already know it's a framed source
365            last_t = ((last_t / input_stream_dt.meta().ref_interval) + 1)
366                * input_stream_dt.meta().ref_interval;
367
368            assert_eq!(event_t_dt.coord.x as i32, event_dt.coord.x as i32);
369            assert_eq!(event_t_dt.coord.y as i32, event_dt.coord.y as i32);
370            assert_eq!(event_t_dt.coord.c, event_dt.coord.c);
371            let dt_mig = event_t_dt.t;
372            let dt_gt = event_dt.t;
373            assert_eq!(dt_mig, dt_gt);
374            assert_eq!(event_t_dt.d, event_dt.d);
375        }
376        assert_eq!(event_count, 333);
377
378        Ok(())
379    }
380
381    #[test]
382    fn test_migrate_v2_bunny_8() -> Result<(), Box<dyn std::error::Error>> {
383        let bufreader = BufReader::new(File::open("./tests/samples/bunny_v2_t_3.adder")?);
384        let compression = RawInput::new();
385        let mut bitreader_t = BitReader::endian(bufreader, BigEndian);
386        let mut input_stream_t = Decoder::new_raw(compression, &mut bitreader_t).unwrap();
387
388        let reconstructed_frame_rate = 30.0;
389
390        let mut frame_sequence_t: FrameSequence<u8> =
391            FramerBuilder::new(input_stream_t.meta().plane, 500)
392                .codec_version(input_stream_t.meta().codec_version, TimeMode::AbsoluteT)
393                .time_parameters(
394                    input_stream_t.meta().tps,
395                    input_stream_t.meta().ref_interval,
396                    input_stream_t.meta().delta_t_max,
397                    Some(reconstructed_frame_rate),
398                )
399                .mode(INSTANTANEOUS)
400                .source(
401                    input_stream_t.get_source_type(),
402                    input_stream_t.meta().source_camera,
403                )
404                .finish();
405
406        let bufreader = BufReader::new(File::open("./tests/samples/bunny_v2_dt_3.adder")?);
407        let compression = RawInput::new();
408        let mut bitreader_dt = BitReader::endian(bufreader, BigEndian);
409        let mut input_stream_dt = Decoder::new_raw(compression, &mut bitreader_dt).unwrap();
410
411        let mut frame_sequence_dt: FrameSequence<u8> =
412            FramerBuilder::new(input_stream_dt.meta().plane, 500)
413                .codec_version(input_stream_dt.meta().codec_version, TimeMode::DeltaT)
414                .time_parameters(
415                    input_stream_dt.meta().tps,
416                    input_stream_dt.meta().ref_interval,
417                    input_stream_dt.meta().delta_t_max,
418                    Some(reconstructed_frame_rate),
419                )
420                .mode(INSTANTANEOUS)
421                .source(
422                    input_stream_dt.get_source_type(),
423                    input_stream_dt.meta().source_camera,
424                )
425                .finish();
426
427        let mut event_count = 0;
428        let mut t_tree: Array3<u32> = Array3::from_shape_vec(
429            (
430                input_stream_dt.meta().plane.h_usize(),
431                input_stream_dt.meta().plane.w_usize(),
432                input_stream_dt.meta().plane.c_usize(),
433            ),
434            vec![0_u32; input_stream_dt.meta().plane.volume()],
435        )?;
436        let mut t_frame: Option<Vec<Array3<Option<u8>>>> = None;
437        let mut dt_frame;
438        loop {
439            let event_t = match input_stream_t.digest_event(&mut bitreader_t) {
440                Ok(ev) => ev,
441                Err(_) => {
442                    break;
443                }
444            };
445            if event_t.coord.y == 15
446                && event_t.coord.x == 123
447                && event_t.coord.c_usize() == 0
448                && event_count > 540
449            {
450                dbg!(event_t);
451            }
452
453            let a_t = frame_sequence_t.ingest_event(&mut event_t.clone(), None);
454
455            if a_t {
456                t_frame = frame_sequence_t.pop_next_frame();
457            }
458
459            let event_dt = match input_stream_dt.digest_event(&mut bitreader_dt) {
460                Ok(ev) => ev,
461                Err(_) => {
462                    break;
463                }
464            };
465            let a_dt = frame_sequence_dt.ingest_event(&mut event_dt.clone(), None);
466
467            if a_dt {
468                dt_frame = frame_sequence_dt.pop_next_frame();
469
470                for c in 0..input_stream_dt.meta().plane.c_usize() {
471                    for y in 0..input_stream_dt.meta().plane.h_usize() {
472                        for x in 0..input_stream_dt.meta().plane.w_usize() {
473                            let dt_val =
474                                dt_frame.clone().unwrap().last().unwrap()[[y, x, c]].unwrap();
475                            let t_val =
476                                t_frame.clone().unwrap().last().unwrap()[[y, x, c]].unwrap();
477                            assert_eq!(dt_val, t_val);
478                        }
479                    }
480                }
481                // assert_eq!(dt_frame.unwrap()[0], t_frame.clone().unwrap()[0]);
482
483                // let dt_val = dt_frame.unwrap()[0][[0, 0, 0]].unwrap();
484                // let t_val = t_frame.clone().unwrap()[0][[0, 0, 0]].unwrap();
485                // assert_eq!(dt_val, t_val);
486            }
487
488            event_count += 1;
489            let last_t = &mut t_tree[[
490                event_t.coord.y_usize(),
491                event_t.coord.x_usize(),
492                event_t.coord.c_usize(),
493            ]];
494
495            let event_t_dt = absolute_event_to_dt_event(event_t, *last_t);
496            *last_t = event_t.t;
497
498            // We already know it's a framed source
499            if *last_t % input_stream_dt.meta().ref_interval != 0 {
500                *last_t = ((*last_t / input_stream_dt.meta().ref_interval) + 1)
501                    * input_stream_dt.meta().ref_interval;
502            }
503
504            assert_eq!(event_t_dt.coord.x as i32, event_dt.coord.x as i32);
505            assert_eq!(event_t_dt.coord.y as i32, event_dt.coord.y as i32);
506            assert_eq!(event_t_dt.coord.c, event_dt.coord.c);
507            let dt_mig = event_t_dt.t;
508            let dt_gt = event_dt.t;
509            assert_eq!(dt_mig, dt_gt);
510            assert_eq!(event_t_dt.d, event_dt.d);
511        }
512        assert_eq!(event_count, 675693);
513
514        Ok(())
515    }
516}