adder_codec_core/codec/compressed/source_model/event_structure/
event_cube.rs

1use crate::codec::compressed::fenwick::context_switching::FenwickModel;
2use crate::codec::compressed::source_model::cabac_contexts::{
3    Contexts, BITSHIFT_ENCODE_FULL, D_RESIDUAL_OFFSET,
4};
5use crate::codec::compressed::source_model::event_structure::BLOCK_SIZE;
6use crate::codec::compressed::source_model::{ComponentCompression, HandleEvent};
7use crate::codec::compressed::{DResidual, TResidual, DRESIDUAL_NO_EVENT, DRESIDUAL_SKIP_CUBE};
8use crate::codec::CodecError;
9use crate::{AbsoluteT, Coord, DeltaT, Event, EventCoordless, PixelAddress, D, D_EMPTY};
10use arithmetic_coding_adder_dep::{Decoder, Encoder};
11use bitstream_io::{BigEndian, BitReader, BitWriter};
12use std::cmp::{max, min};
13use std::collections::VecDeque;
14use std::io::Cursor;
15use std::mem::size_of;
16
17type Pixel = Vec<EventCoordless>;
18
19type EventLists = [[[Pixel; BLOCK_SIZE]; BLOCK_SIZE]; 3];
20
21#[derive(PartialEq, Debug, Clone, Default)]
22pub struct EventCube {
23    /// The absolute y-coordinate of the top-left pixel in the cube
24    pub(crate) start_y: PixelAddress,
25
26    /// The absolute x-coordinate of the top-left pixel in the cube
27    pub(crate) start_x: PixelAddress,
28
29    num_channels: usize,
30
31    /// Contains the sparse events in the cube. The index is the relative interval of dt_ref from the start
32    pub(crate) raw_event_lists: EventLists,
33
34    /// The absolute time of the cube's beginning (not necessarily aligned to an event. We structure
35    /// cubes to be in temporal lockstep at the beginning.)
36    pub(crate) start_t: AbsoluteT,
37
38    /// How many ticks each input interval spans
39    dt_ref: DeltaT,
40
41    /// How many dt_ref intervals the whole cube spans
42    num_intervals: usize,
43
44    raw_event_memory: [[[EventCoordless; BLOCK_SIZE]; BLOCK_SIZE]; 3],
45
46    skip_cube: bool,
47
48    decompressed_event_queue: VecDeque<Event>,
49}
50
51impl EventCube {
52    pub fn new(
53        start_y: PixelAddress,
54        start_x: PixelAddress,
55        num_channels: usize,
56        start_t: AbsoluteT,
57        dt_ref: DeltaT,
58        num_intervals: usize,
59    ) -> Self {
60        let row: [Pixel; BLOCK_SIZE] = vec![Vec::with_capacity(num_intervals); BLOCK_SIZE]
61            .try_into()
62            .unwrap();
63        let square: [[Pixel; BLOCK_SIZE]; BLOCK_SIZE] = vec![row; BLOCK_SIZE].try_into().unwrap();
64        let lists = [square.clone(), square.clone(), square];
65
66        Self {
67            start_y,
68            start_x,
69            num_channels,
70            raw_event_lists: lists,
71            start_t,
72            dt_ref,
73            num_intervals,
74            raw_event_memory: [[[EventCoordless::default(); BLOCK_SIZE]; BLOCK_SIZE]; 3],
75            skip_cube: true,
76            decompressed_event_queue: Default::default(),
77        }
78    }
79}
80
81fn generate_t_prediction(
82    idx: usize,
83    mut d_residual: DResidual,
84    last_delta_t: DeltaT,
85    prev_event: &EventCoordless,
86    num_intervals: usize,
87    dt_ref: DeltaT,
88    start_t: AbsoluteT,
89) -> AbsoluteT {
90    if idx == 1 {
91        // We don't have a deltaT context
92        start_t + last_delta_t as AbsoluteT
93    } else {
94        if d_residual.abs() > 14 {
95            d_residual = 0;
96        }
97        if prev_event.d == D_EMPTY {
98            d_residual = -1;
99        }
100        // We've gotten the DeltaT between the last two events. Use that
101        // to form our prediction
102        let delta_t_prediction: DeltaT = if d_residual < 0 {
103            last_delta_t >> -d_residual
104        } else {
105            last_delta_t << d_residual
106        };
107        max(
108            prev_event.t,
109            prev_event.t
110                + min(delta_t_prediction, (num_intervals as u8) as u32 * dt_ref) as AbsoluteT,
111        )
112    }
113}
114
115impl HandleEvent for EventCube {
116    /// Take in a raw event and place it at the appropriate location.
117    ///
118    /// Assume that the event does fit within the cube's time frame. This is checked at the caller.
119    ///
120    /// Returns true if this is the first event the cube has ingested
121    fn ingest_event(&mut self, mut event: Event) -> bool {
122        event.coord.y -= self.start_y;
123        event.coord.x -= self.start_x;
124
125        let item = EventCoordless::from(event);
126
127        if self.raw_event_lists[event.coord.c_usize()][event.coord.y_usize()][event.coord.x_usize()]
128            .len()
129            > 1
130        {
131            let last = self.raw_event_lists[event.coord.c_usize()][event.coord.y_usize()]
132                [event.coord.x_usize()][self.raw_event_lists[event.coord.c_usize()]
133                [event.coord.y_usize()][event.coord.x_usize()]
134            .len()
135                - 1];
136            if event.t <= last.t {
137                // dbg!(event.t, last.t);
138                return false;
139            }
140            debug_assert!(event.t >= last.t);
141        }
142
143        self.raw_event_lists[event.coord.c_usize()][event.coord.y_usize()][event.coord.x_usize()]
144            .push(item);
145
146        self.raw_event_memory[event.coord.c_usize()][event.coord.y_usize()]
147            [event.coord.x_usize()] = EventCoordless::from(event);
148
149        if self.skip_cube {
150            self.skip_cube = false;
151            true
152        } else {
153            false
154        }
155    }
156
157    fn digest_event(&mut self) -> Result<Event, CodecError> {
158        if self.skip_cube {
159            return Err(CodecError::NoMoreEvents);
160            // return Err(CodecError::new(
161            //     "Tried to digest an event from a cube that's been skipped",
162            // ));
163        } else if self.decompressed_event_queue.is_empty() {
164            // Then we need to convert all the cube events back into actual events and queue them up
165            for c in 0..self.num_channels {
166                for y in 0..BLOCK_SIZE {
167                    for x in 0..BLOCK_SIZE {
168                        if !self.raw_event_lists[c][y][x].is_empty() {
169                            for event in self.raw_event_lists[c][y][x].iter() {
170                                let event = Event {
171                                    coord: Coord {
172                                        x: x as PixelAddress + self.start_x,
173                                        y: y as PixelAddress + self.start_y,
174                                        c: if self.num_channels == 1 {
175                                            None
176                                        } else {
177                                            Some(c as u8)
178                                        },
179                                    },
180                                    d: event.d,
181                                    t: event.t,
182                                };
183                                self.decompressed_event_queue.push_back(event);
184                            }
185                        }
186                    }
187                }
188            }
189        }
190
191        if let Some(event) = self.decompressed_event_queue.pop_front() {
192            if self.decompressed_event_queue.is_empty() {
193                self.skip_cube = true;
194            }
195            Ok(event)
196        } else {
197            Err(CodecError::NoMoreEvents)
198        }
199    }
200
201    /// Clear out the cube's events and increment the start time by the cube's duration
202    fn clear_compression(&mut self) {
203        for c in 0..3 {
204            for y in 0..BLOCK_SIZE {
205                for x in 0..BLOCK_SIZE {
206                    self.raw_event_lists[c][y][x].clear();
207                }
208            }
209        }
210        self.start_t += self.num_intervals as AbsoluteT * self.dt_ref;
211        self.skip_cube = true;
212    }
213    fn clear_decompression(&mut self) {
214        for c in 0..3 {
215            for y in 0..BLOCK_SIZE {
216                for x in 0..BLOCK_SIZE {
217                    self.raw_event_lists[c][y][x].clear();
218                }
219            }
220        }
221        self.start_t += self.num_intervals as AbsoluteT * self.dt_ref;
222        self.skip_cube = true;
223    }
224}
225
226#[cfg(test)]
227mod build_tests {
228    use super::EventCube;
229    use crate::codec::compressed::source_model::HandleEvent;
230    use crate::{Coord, Event};
231
232    /// Create an empty cube
233    #[test]
234    fn create_cube() -> Result<(), Box<dyn std::error::Error>> {
235        let cube = EventCube::new(16, 16, 1, 255, 255, 2550);
236        assert_eq!(cube.start_y, 16);
237        assert_eq!(cube.start_x, 16);
238
239        Ok(())
240    }
241
242    /// Create a cube and add several sparse events to it
243    fn fill_cube() -> Result<EventCube, Box<dyn std::error::Error>> {
244        let mut cube = EventCube::new(16, 16, 1, 255, 255, 2550);
245        assert_eq!(cube.start_y, 16);
246        assert_eq!(cube.start_x, 16);
247
248        cube.ingest_event(Event {
249            coord: Coord {
250                x: 27,
251                y: 17,
252                c: None,
253            },
254            t: 280,
255            d: 7,
256        });
257
258        cube.ingest_event(Event {
259            coord: Coord {
260                x: 27,
261                y: 17,
262                c: None,
263            },
264            t: 285,
265            d: 7,
266        });
267
268        cube.ingest_event(Event {
269            coord: Coord {
270                x: 29,
271                y: 17,
272                c: None,
273            },
274            t: 290,
275            d: 7,
276        });
277
278        Ok(cube)
279    }
280    #[test]
281    fn test_fill_cube() -> Result<(), Box<dyn std::error::Error>> {
282        let cube = fill_cube()?;
283        assert!(cube.raw_event_lists[0][0][0].is_empty());
284        assert_eq!(cube.raw_event_lists[0][1][13].len(), 1);
285
286        Ok(())
287    }
288
289    #[test]
290    fn fill_second_cube() -> Result<(), Box<dyn std::error::Error>> {
291        let mut cube = fill_cube()?;
292        cube.clear_compression();
293        assert_eq!(cube.raw_event_lists[0][1][13].len(), 0);
294        cube.ingest_event(Event {
295            coord: Coord {
296                x: 29,
297                y: 17,
298                c: None,
299            },
300            t: 500,
301            d: 7,
302        });
303        assert_eq!(cube.raw_event_lists[0][1][13].len(), 1);
304        Ok(())
305    }
306}
307
308impl ComponentCompression for EventCube {
309    fn compress_intra(
310        &mut self,
311        encoder: &mut Encoder<FenwickModel, BitWriter<Vec<u8>, BigEndian>>,
312        contexts: &Contexts,
313        stream: &mut BitWriter<Vec<u8>, BigEndian>,
314        _: Option<u8>,
315    ) -> Result<(), CodecError> {
316        encoder.model.set_context(contexts.d_context);
317        if self.skip_cube {
318            // If we're skipping this cube, just encode a NO_EVENT symbol
319            let tmp = (DRESIDUAL_SKIP_CUBE + D_RESIDUAL_OFFSET) as usize;
320            encoder.encode(Some(&tmp), stream).unwrap();
321            // for byte in (DRESIDUAL_SKIP_CUBE).to_be_bytes().iter() {
322            //     encoder.encode(Some(&(*byte as usize)), stream).unwrap();
323            // }
324            return Ok(()); // We're done
325        }
326
327        let mut init_event: Option<EventCoordless> = None;
328        let mut d_residual = 0;
329
330        // Intra-code the first event (if present) for each pixel in row-major order
331        for c in 0..self.num_channels {
332            self.raw_event_lists[c].iter_mut().for_each(|row| {
333                row.iter_mut().for_each(|pixel| {
334                    encoder.model.set_context(contexts.d_context);
335
336                    if !pixel.is_empty() {
337                        let event = pixel.first_mut().unwrap();
338
339                        if let Some(init) = &mut init_event {
340                            d_residual = event.d as DResidual - init.d as DResidual;
341                            // Write the D residual (relative to the start_d for the first event)
342
343                            let tmp = (d_residual + D_RESIDUAL_OFFSET) as usize;
344                            encoder.encode(Some(&tmp), stream).unwrap();
345                            //     for byte in d_residual.to_be_bytes().iter() {
346                            //     encoder.encode(Some(&(*byte as usize)), stream).unwrap();
347                            // }
348                        } else {
349                            // Write the first event's D directly
350                            let tmp = (event.d as DResidual + D_RESIDUAL_OFFSET) as usize;
351                            encoder.encode(Some(&tmp), stream).unwrap();
352                            // for byte in (event.d as DResidual).to_be_bytes().iter() {
353                            //     encoder.encode(Some(&(*byte as usize)), stream).unwrap();
354                            // }
355
356                            // Create the init event with t being the start_t of the cube
357                            init_event = Some(EventCoordless {
358                                d: event.d,
359                                t: self.start_t,
360                            })
361                        }
362
363                        if let Some(init) = &mut init_event {
364                            // Don't do any special prediction here (yet). Just predict the same t as previously found.
365                            let t_residual_i64 = event.t as i64 - init.t as i64;
366                            let (bitshift_amt, t_residual) =
367                                contexts.residual_to_bitshift(t_residual_i64);
368                            // contexts.residual_to_bitshift2(
369                            //     init.t as i64,
370                            //     t_residual_i64,
371                            //     event,
372                            //     init,
373                            //     self.dt_ref
374                            // );
375
376                            encoder.model.set_context(contexts.bitshift_context);
377                            for byte in bitshift_amt.to_be_bytes().iter() {
378                                encoder.encode(Some(&(*byte as usize)), stream).unwrap();
379                            }
380
381                            encoder.model.set_context(contexts.t_context);
382
383                            if bitshift_amt == BITSHIFT_ENCODE_FULL {
384                                for byte in t_residual.to_be_bytes().iter() {
385                                    encoder.encode(Some(&(*byte as usize)), stream).unwrap();
386                                }
387                                event.t = (init.t as i64 + t_residual) as AbsoluteT;
388                            } else {
389                                let t_residual = t_residual as TResidual;
390                                for byte in t_residual.to_be_bytes().iter() {
391                                    encoder.encode(Some(&(*byte as usize)), stream).unwrap();
392                                }
393                                // Shift it back for the event, so we base our next prediction on the reconstructed value!
394                                // if bitshift_amt != 0 {
395                                event.t = (init.t as i64
396                                    + ((t_residual as i64) << bitshift_amt as i64))
397                                    as AbsoluteT;
398                            }
399                            debug_assert!(event.t < 2_u32.pow(31));
400
401                            *init = *event;
402                        } else {
403                            panic!("No init event");
404                        }
405                    } else {
406                        // Else there's no event for this pixel. Encode a NO_EVENT symbol.
407                        let tmp = (DRESIDUAL_NO_EVENT + D_RESIDUAL_OFFSET) as usize;
408                        encoder.encode(Some(&tmp), stream).unwrap();
409                        // for byte in (DRESIDUAL_NO_EVENT).to_be_bytes().iter() {
410                        //     encoder.encode(Some(&(*byte as usize)), stream).unwrap();
411                        // }
412                    }
413                })
414            })
415        }
416        Ok(())
417    }
418
419    fn compress_inter(
420        &mut self,
421        encoder: &mut Encoder<FenwickModel, BitWriter<Vec<u8>, BigEndian>>,
422        contexts: &Contexts,
423        stream: &mut BitWriter<Vec<u8>, BigEndian>,
424        c_thresh_max: Option<u8>,
425    ) -> Result<(), CodecError> {
426        if self.skip_cube {
427            return Ok(());
428        }
429        let c_thresh_max = c_thresh_max.unwrap_or(7);
430        for c in 0..self.num_channels {
431            self.raw_event_lists[c].iter_mut().for_each(|row| {
432                row.iter_mut().for_each(|pixel| {
433                    if !pixel.is_empty() {
434                        let mut idx = 1;
435                        let mut last_delta_t: DeltaT = 0;
436                        loop {
437                            encoder.model.set_context(contexts.d_context);
438
439                            if idx < pixel.len() {
440                                // TODO: don't copy the below event?
441                                let prev_event = pixel[idx - 1]; // We can assume for now that this is perfectly decoded, but later we'll corrupt it according to any loss we incur
442                                let event = &mut pixel[idx];
443
444                                // Get the D residual
445                                let d_residual = event.d as DResidual - prev_event.d as DResidual;
446                                // Write the D residual (relative to the start_d for the first event)
447                                for byte in d_residual.to_be_bytes().iter() {
448                                    encoder.encode(Some(&(*byte as usize)), stream).unwrap();
449                                }
450
451                                let t_prediction = generate_t_prediction(
452                                    idx,
453                                    d_residual,
454                                    last_delta_t,
455                                    &prev_event,
456                                    self.num_intervals,
457                                    self.dt_ref,
458                                    self.start_t,
459                                );
460
461                                // encoder.model.set_context(contexts.dtref_context);
462                                let t_residual_i64 = event.t as i64 - t_prediction as i64;
463                                let (bitshift_amt, t_residual) = contexts.residual_to_bitshift2(
464                                    t_prediction as i64,
465                                    t_residual_i64,
466                                    event,
467                                    &prev_event,
468                                    self.dt_ref,
469                                    c_thresh_max as f64,
470                                );
471
472                                encoder.model.set_context(contexts.bitshift_context);
473                                for byte in bitshift_amt.to_be_bytes().iter() {
474                                    encoder.encode(Some(&(*byte as usize)), stream).unwrap();
475                                }
476
477                                encoder.model.set_context(contexts.t_context);
478
479                                if bitshift_amt == BITSHIFT_ENCODE_FULL {
480                                    for byte in t_residual.to_be_bytes().iter() {
481                                        encoder.encode(Some(&(*byte as usize)), stream).unwrap();
482                                    }
483                                    event.t = (t_prediction as i64 + t_residual) as AbsoluteT;
484                                    // debug_assert!(event.t < 5000000);
485                                } else {
486                                    let t_residual = t_residual as TResidual;
487                                    for byte in t_residual.to_be_bytes().iter() {
488                                        encoder.encode(Some(&(*byte as usize)), stream).unwrap();
489                                    }
490                                    // Shift it back for the event, so we base our next prediction on the reconstructed value!
491                                    // if bitshift_amt != 0 {
492                                    event.t = (t_prediction as i64
493                                        + ((t_residual as i64) << bitshift_amt as i64))
494                                        as AbsoluteT;
495                                    // debug_assert!(event.t < 5000000);
496                                }
497
498                                event.t = max(event.t, prev_event.t);
499                                debug_assert!(event.t >= prev_event.t);
500                                last_delta_t = (event.t - prev_event.t) as DeltaT;
501                            } else {
502                                encoder.model.set_context(contexts.d_context);
503                                // Else there's no other event for this pixel. Encode a NO_EVENT symbol.
504                                for byte in (DRESIDUAL_NO_EVENT).to_be_bytes().iter() {
505                                    encoder.encode(Some(&(*byte as usize)), stream).unwrap();
506                                }
507
508                                break;
509                            }
510                            idx += 1;
511                        }
512                    }
513                })
514            })
515        }
516        Ok(())
517    }
518
519    fn decompress_intra(
520        &mut self,
521        decoder: &mut Decoder<FenwickModel, BitReader<Cursor<Vec<u8>>, BigEndian>>,
522        contexts: &Contexts,
523        stream: &mut BitReader<Cursor<Vec<u8>>, BigEndian>,
524        start_t: AbsoluteT,
525    ) {
526        let mut bitshift_buffer = [0u8; 1];
527        let mut t_residual_buffer = [0u8; size_of::<TResidual>()];
528        let mut t_residual_full_buffer = [0u8; size_of::<i64>()];
529        let mut init_event: Option<EventCoordless> = None;
530
531        for c in 0..self.num_channels {
532            for y in 0..BLOCK_SIZE {
533                for x in 0..BLOCK_SIZE {
534                    let pixel = &mut self.raw_event_lists[c][y][x];
535
536                    decoder.model.set_context(contexts.d_context);
537
538                    let tmp = decoder.decode(stream).unwrap().unwrap();
539                    let d_residual = tmp as i16 - D_RESIDUAL_OFFSET;
540
541                    if d_residual == DRESIDUAL_SKIP_CUBE {
542                        pixel.clear(); // So we can skip it for intra-coding
543                        self.skip_cube = true;
544                        return;
545                    } else if d_residual == DRESIDUAL_NO_EVENT {
546                        pixel.clear(); // So we can skip it for intra-coding
547                    } else {
548                        let d = if let Some(init) = &mut init_event {
549                            (init.d as DResidual + d_residual) as D
550                        } else {
551                            // There is no init event
552                            init_event = Some(EventCoordless { d: 0, t: start_t });
553                            self.skip_cube = false;
554                            d_residual as D
555                        };
556
557                        if let Some(init) = &mut init_event {
558                            // decoder.model.set_context(contexts.dtref_context);
559                            // for byte in dtref_residual_buffer.iter_mut() {
560                            //     *byte = decoder.decode(stream).unwrap().unwrap() as u8;
561                            // }
562                            // let dtref_residual = DResidual::from_be_bytes(dtref_residual_buffer);
563
564                            decoder.model.set_context(contexts.bitshift_context);
565                            for byte in bitshift_buffer.iter_mut() {
566                                *byte = decoder.decode(stream).unwrap().unwrap() as u8;
567                            }
568                            let bitshift_amt = bitshift_buffer[0];
569
570                            decoder.model.set_context(contexts.t_context);
571                            let t_residual = if bitshift_amt == BITSHIFT_ENCODE_FULL {
572                                for byte in t_residual_full_buffer.iter_mut() {
573                                    *byte = decoder.decode(stream).unwrap().unwrap() as u8;
574                                }
575                                i64::from_be_bytes(t_residual_full_buffer)
576                            } else {
577                                for byte in t_residual_buffer.iter_mut() {
578                                    *byte = decoder.decode(stream).unwrap().unwrap() as u8;
579                                }
580                                let t_residual = TResidual::from_be_bytes(t_residual_buffer) as i64;
581                                (t_residual) << bitshift_amt as i64
582                            };
583
584                            init.d = (init.d as DResidual + d_residual) as D;
585
586                            debug_assert!(init.t as i64 + t_residual >= 0);
587                            init.t = (init.t as i64 + t_residual) as AbsoluteT;
588
589                            // debug_assert!(init.t < start_t + num_intervals as AbsoluteT * dt_ref);
590                            pixel.push(EventCoordless { d, t: init.t });
591                        } else {
592                            panic!("No init event");
593                        }
594                    }
595                }
596            }
597        }
598    }
599
600    fn decompress_inter(
601        &mut self,
602        decoder: &mut Decoder<FenwickModel, BitReader<Cursor<Vec<u8>>, BigEndian>>,
603        contexts: &Contexts,
604        stream: &mut BitReader<Cursor<Vec<u8>>, BigEndian>,
605    ) {
606        if self.skip_cube {
607            return;
608        }
609        let mut d_residual_buffer = [0u8; size_of::<DResidual>()];
610        let mut t_residual_buffer = [0u8; size_of::<TResidual>()];
611        let mut t_residual_full_buffer = [0u8; size_of::<i64>()];
612        let mut bitshift_buffer = [0u8; 1];
613
614        for c in 0..self.num_channels {
615            self.raw_event_lists[c].iter_mut().for_each(|row| {
616                row.iter_mut().for_each(|pixel| {
617                    if !pixel.is_empty() {
618                        // Then look for the next events for this pixel
619                        let mut idx = 1;
620                        let mut last_delta_t = 0;
621                        loop {
622                            decoder.model.set_context(contexts.d_context);
623
624                            for byte in d_residual_buffer.iter_mut() {
625                                *byte = decoder.decode(stream).unwrap().unwrap() as u8;
626                            }
627                            let d_residual = DResidual::from_be_bytes(d_residual_buffer);
628
629                            if d_residual == DRESIDUAL_NO_EVENT {
630                                break; // We have all the events for this pixel now
631                            }
632                            debug_assert!(idx - 1 < pixel.len());
633                            let prev_event = pixel[idx - 1];
634
635                            let d = (prev_event.d as DResidual + d_residual) as D;
636
637                            let t_prediction = generate_t_prediction(
638                                idx,
639                                d_residual,
640                                last_delta_t,
641                                &prev_event,
642                                self.num_intervals,
643                                self.dt_ref,
644                                self.start_t,
645                            );
646
647                            decoder.model.set_context(contexts.bitshift_context);
648                            for byte in bitshift_buffer.iter_mut() {
649                                *byte = decoder.decode(stream).unwrap().unwrap() as u8;
650                            }
651                            let bitshift_amt = bitshift_buffer[0];
652
653                            decoder.model.set_context(contexts.t_context);
654                            let t_residual = if bitshift_amt == BITSHIFT_ENCODE_FULL {
655                                for byte in t_residual_full_buffer.iter_mut() {
656                                    *byte = decoder.decode(stream).unwrap().unwrap() as u8;
657                                }
658                                i64::from_be_bytes(t_residual_full_buffer)
659                            } else {
660                                for byte in t_residual_buffer.iter_mut() {
661                                    *byte = decoder.decode(stream).unwrap().unwrap() as u8;
662                                }
663                                let t_residual = TResidual::from_be_bytes(t_residual_buffer) as i64;
664                                (t_residual) << bitshift_amt as i64
665                            };
666
667                            let t = max(
668                                (t_prediction as i64 + t_residual) as AbsoluteT,
669                                prev_event.t,
670                            );
671                            debug_assert!(t >= prev_event.t);
672                            last_delta_t = (t - prev_event.t) as DeltaT;
673                            // debug_assert!(
674                            //     t <= self.start_t + self.num_intervals as AbsoluteT * self.dt_ref
675                            // );
676                            pixel.push(EventCoordless { d, t });
677
678                            idx += 1;
679                        }
680                    }
681                });
682            });
683        }
684    }
685}
686
687#[cfg(test)]
688mod compression_tests {
689    use crate::codec::compressed::fenwick::context_switching::FenwickModel;
690    use crate::codec::compressed::source_model::cabac_contexts::eof_context;
691    use crate::codec::compressed::source_model::event_structure::event_cube::EventCube;
692    use crate::codec::compressed::source_model::{ComponentCompression, HandleEvent};
693    use crate::{Coord, Event};
694    use arithmetic_coding_adder_dep::Encoder;
695    use bitstream_io::{BigEndian, BitReader, BitWriter};
696    use rand::prelude::StdRng;
697    use rand::{Rng, SeedableRng};
698    use std::cmp::min;
699    use std::error::Error;
700    use std::io::Cursor;
701
702    #[test]
703    fn compress_and_decompress_intra() -> Result<(), Box<dyn Error>> {
704        let mut cube = EventCube::new(0, 0, 1, 255, 255, 10);
705        let mut counter = 0;
706        for _ in 0..3 {
707            for y in 0..16 {
708                for x in 0..15 {
709                    cube.ingest_event(Event {
710                        coord: Coord { x, y, c: None },
711                        t: 280 + counter,
712                        d: 7,
713                    });
714                    counter += 1;
715                }
716            }
717        }
718
719        let bufwriter = Vec::new();
720        let mut stream = BitWriter::endian(bufwriter, BigEndian);
721
722        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
723        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
724            &mut source_model,
725            255,
726        );
727
728        let mut encoder = Encoder::new(source_model);
729
730        cube.compress_intra(&mut encoder, &contexts, &mut stream, None)?;
731        eof_context(&contexts, &mut encoder, &mut stream);
732
733        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
734        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
735            &mut source_model,
736            255,
737        );
738        let mut decoder = arithmetic_coding_adder_dep::Decoder::new(source_model);
739        let mut stream = BitReader::endian(Cursor::new(stream.into_writer()), BigEndian);
740
741        let mut cube2 = cube.clone();
742
743        cube2.decompress_intra(&mut decoder, &contexts, &mut stream, 255);
744
745        for c in 0..3 {
746            for y in 0..16 {
747                for x in 0..16 {
748                    dbg!(c, y, x);
749                    dbg!(
750                        &cube.raw_event_lists[c][y][x],
751                        &cube2.raw_event_lists[c][y][x]
752                    );
753                    if !cube.raw_event_lists[c][y][x].is_empty() {
754                        assert!(!cube2.raw_event_lists[c][y][x].is_empty());
755                        assert_eq!(
756                            cube.raw_event_lists[c][y][x][0],
757                            cube2.raw_event_lists[c][y][x][0]
758                        );
759                    } else {
760                        assert!(cube2.raw_event_lists[c][y][x].is_empty());
761                    }
762                }
763            }
764        }
765
766        Ok(())
767    }
768
769    #[test]
770    fn compress_and_decompress_inter() -> Result<(), Box<dyn Error>> {
771        let mut cube = EventCube::new(0, 0, 1, 255, 255, 2);
772        let mut counter = 0;
773        for _ in 0..3 {
774            for y in 0..16 {
775                for x in 0..15 {
776                    cube.ingest_event(Event {
777                        coord: Coord { x, y, c: None },
778                        t: min(
779                            280 + counter,
780                            cube.start_t + (cube.num_intervals as u32 - 1) * cube.dt_ref,
781                        ),
782                        d: 7,
783                    });
784                    counter += 1;
785                }
786            }
787        }
788
789        let mut rng = StdRng::seed_from_u64(1234);
790
791        for y in 0..16 {
792            for x in 0..15 {
793                for _ in 0..rng.gen_range(0..3) {
794                    cube.ingest_event(Event {
795                        coord: Coord { x, y, c: None },
796                        t: min(
797                            280 + counter,
798                            cube.start_t + (cube.num_intervals as u32 - 1) * cube.dt_ref,
799                        ),
800                        d: rng.gen_range(4..12),
801                    });
802                    counter += 1;
803                }
804            }
805        }
806
807        let bufwriter = Vec::new();
808        let mut stream = BitWriter::endian(bufwriter, BigEndian);
809
810        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
811        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
812            &mut source_model,
813            255,
814        );
815
816        let mut encoder = Encoder::new(source_model);
817
818        cube.compress_intra(&mut encoder, &contexts, &mut stream, Some(0))?;
819        cube.compress_inter(&mut encoder, &contexts, &mut stream, Some(0))?;
820
821        eof_context(&contexts, &mut encoder, &mut stream);
822
823        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
824        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
825            &mut source_model,
826            255,
827        );
828        let mut decoder = arithmetic_coding_adder_dep::Decoder::new(source_model);
829        let mut stream = BitReader::endian(Cursor::new(stream.into_writer()), BigEndian);
830
831        let mut cube2 = cube.clone();
832        cube2.decompress_intra(&mut decoder, &contexts, &mut stream, 255);
833        cube2.decompress_inter(&mut decoder, &contexts, &mut stream);
834
835        for c in 0..3 {
836            for y in 0..16 {
837                for x in 0..16 {
838                    if !cube.raw_event_lists[c][y][x].is_empty() {
839                        assert!(!cube2.raw_event_lists[c][y][x].is_empty());
840                        assert_eq!(
841                            cube.raw_event_lists[c][y][x][0],
842                            cube2.raw_event_lists[c][y][x][0]
843                        );
844                        for i in 0..cube.raw_event_lists[c][y][x].len() {
845                            assert_eq!(
846                                cube.raw_event_lists[c][y][x][i],
847                                cube2.raw_event_lists[c][y][x][i]
848                            );
849                        }
850                    } else {
851                        assert!(cube2.raw_event_lists[c][y][x].is_empty());
852                    }
853                }
854            }
855        }
856
857        Ok(())
858    }
859
860    #[test]
861    fn compress_and_decompress_empty() -> Result<(), Box<dyn Error>> {
862        let mut cube = EventCube::new(0, 0, 1, 255, 255, 10);
863
864        let bufwriter = Vec::new();
865        let mut stream = BitWriter::endian(bufwriter, BigEndian);
866
867        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
868        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
869            &mut source_model,
870            255,
871        );
872
873        let mut encoder = Encoder::new(source_model);
874
875        cube.compress_intra(&mut encoder, &contexts, &mut stream, Some(0))?;
876        cube.compress_inter(&mut encoder, &contexts, &mut stream, Some(0))?;
877
878        eof_context(&contexts, &mut encoder, &mut stream);
879
880        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
881        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
882            &mut source_model,
883            255,
884        );
885        let mut decoder = arithmetic_coding_adder_dep::Decoder::new(source_model);
886        let mut stream = BitReader::endian(Cursor::new(stream.into_writer()), BigEndian);
887
888        let mut cube2 = cube.clone();
889        cube2.decompress_intra(&mut decoder, &contexts, &mut stream, 255);
890        cube2.decompress_inter(&mut decoder, &contexts, &mut stream);
891
892        for c in 0..3 {
893            for y in 0..16 {
894                for x in 0..16 {
895                    if !cube.raw_event_lists[c][y][x].is_empty() {
896                        assert!(!cube2.raw_event_lists[c][y][x].is_empty());
897                        assert_eq!(
898                            cube.raw_event_lists[c][y][x][0],
899                            cube2.raw_event_lists[c][y][x][0]
900                        );
901                        assert_eq!(
902                            cube.raw_event_lists[c][y][x],
903                            cube2.raw_event_lists[c][y][x]
904                        );
905                    } else {
906                        assert!(cube2.raw_event_lists[c][y][x].is_empty());
907                    }
908                }
909            }
910        }
911
912        Ok(())
913    }
914
915    #[test]
916    fn compress_and_decompress_intra_huge_tresidual() -> Result<(), Box<dyn Error>> {
917        let num_intervals = 2;
918        let mut cube = EventCube::new(0, 0, 1, 255000, 255, num_intervals);
919
920        cube.ingest_event(Event {
921            coord: Coord {
922                x: 3,
923                y: 3,
924                c: None,
925            },
926            t: 255001,
927            d: 7,
928        });
929        cube.ingest_event(Event {
930            coord: Coord {
931                x: 4,
932                y: 3,
933                c: None,
934            },
935            t: 280,
936            d: 7,
937        });
938
939        let bufwriter = Vec::new();
940        let mut stream = BitWriter::endian(bufwriter, BigEndian);
941
942        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
943        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
944            &mut source_model,
945            255,
946        );
947
948        let mut encoder = Encoder::new(source_model);
949
950        cube.compress_intra(&mut encoder, &contexts, &mut stream, Some(0))?;
951        cube.compress_inter(&mut encoder, &contexts, &mut stream, Some(0))?;
952
953        eof_context(&contexts, &mut encoder, &mut stream);
954
955        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
956        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
957            &mut source_model,
958            255,
959        );
960        let mut decoder = arithmetic_coding_adder_dep::Decoder::new(source_model);
961        let mut stream = BitReader::endian(Cursor::new(stream.into_writer()), BigEndian);
962
963        let mut cube2 = cube.clone();
964        cube2.decompress_intra(&mut decoder, &contexts, &mut stream, 255000);
965        cube2.decompress_inter(&mut decoder, &contexts, &mut stream);
966
967        // Note that these may NOT be the original values we ingested, due to the bit shifting!
968        assert_eq!(
969            cube.raw_event_lists[0][3][3][0].t,
970            cube2.raw_event_lists[0][3][3][0].t
971        );
972        assert_eq!(
973            cube.raw_event_lists[0][3][4][0].t,
974            cube2.raw_event_lists[0][3][4][0].t
975        );
976
977        Ok(())
978    }
979
980    #[test]
981    fn compress_and_decompress_inter_huge_tresidual() -> Result<(), Box<dyn Error>> {
982        let num_intervals = 2;
983        let mut cube = EventCube::new(0, 0, 1, 255000, 255, num_intervals);
984
985        cube.ingest_event(Event {
986            coord: Coord {
987                x: 3,
988                y: 3,
989                c: None,
990            },
991            t: 255001,
992            d: 7,
993        });
994        cube.ingest_event(Event {
995            coord: Coord {
996                x: 4,
997                y: 3,
998                c: None,
999            },
1000            t: 280,
1001            d: 7,
1002        });
1003        cube.ingest_event(Event {
1004            coord: Coord {
1005                x: 4,
1006                y: 3,
1007                c: None,
1008            },
1009            t: 255001,
1010            d: 7,
1011        });
1012
1013        let bufwriter = Vec::new();
1014        let mut stream = BitWriter::endian(bufwriter, BigEndian);
1015
1016        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
1017        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
1018            &mut source_model,
1019            255,
1020        );
1021
1022        let mut encoder = Encoder::new(source_model);
1023
1024        cube.compress_intra(&mut encoder, &contexts, &mut stream, Some(0))?;
1025        cube.compress_inter(&mut encoder, &contexts, &mut stream, Some(0))?;
1026
1027        eof_context(&contexts, &mut encoder, &mut stream);
1028
1029        let mut source_model = FenwickModel::with_symbols(u16::MAX as usize, 1 << 30);
1030        let contexts = crate::codec::compressed::source_model::cabac_contexts::Contexts::new(
1031            &mut source_model,
1032            255,
1033        );
1034        let mut decoder = arithmetic_coding_adder_dep::Decoder::new(source_model);
1035        let mut stream = BitReader::endian(Cursor::new(stream.into_writer()), BigEndian);
1036
1037        let mut cube2 = cube.clone();
1038        cube2.decompress_intra(&mut decoder, &contexts, &mut stream, 255000);
1039
1040        cube2.decompress_inter(&mut decoder, &contexts, &mut stream);
1041
1042        // Note that these may NOT be the original values we ingested, due to the bit shifting!
1043        assert_eq!(
1044            cube.raw_event_lists[0][3][3][0].t,
1045            cube2.raw_event_lists[0][3][3][0].t
1046        );
1047        assert_eq!(
1048            cube.raw_event_lists[0][3][4][0].t,
1049            cube2.raw_event_lists[0][3][4][0].t
1050        );
1051        assert_eq!(
1052            cube.raw_event_lists[0][3][4][1].t,
1053            cube2.raw_event_lists[0][3][4][1].t
1054        );
1055
1056        Ok(())
1057    }
1058}