1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::{PlaneSize, SourceCamera, TimeMode};
use serde::{Deserialize, Serialize};

pub(crate) type Magic = [u8; 5];
pub(crate) const MAGIC_RAW: Magic = [97, 100, 100, 101, 114]; // 'adder' in ASCII
pub(crate) const MAGIC_COMPRESSED: Magic = [97, 100, 100, 101, 99]; // 'addec' in ASCII

/// ADΔER event stream header
///
/// Both the raw (uncompressed) and compressed ADΔER streams have the same header structure. All
/// that changes is the [`Magic`]. A new `version` of the raw stream format necessitates a new
/// `version` of the compressed format.
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub(crate) struct EventStreamHeader {
    pub(crate) magic: Magic,
    pub(crate) version: u8,
    pub(crate) endianness: u8, // 'b' = big endian
    pub(crate) width: u16,
    pub(crate) height: u16,
    pub(crate) tps: u32,
    pub(crate) ref_interval: u32,
    pub(crate) delta_t_max: u32,
    pub(crate) event_size: u8,
    pub(crate) channels: u8,
}

pub(crate) trait HeaderExtension {}
#[derive(Debug, Default, Serialize, Deserialize)]
pub(crate) struct EventStreamHeaderExtensionV0 {}
impl HeaderExtension for EventStreamHeaderExtensionV0 {}

#[derive(Debug, Default, Serialize, Deserialize)]
pub(crate) struct EventStreamHeaderExtensionV1 {
    pub(crate) source: SourceCamera,
}
impl HeaderExtension for EventStreamHeaderExtensionV1 {}

#[derive(Debug, Default, Serialize, Deserialize)]
pub(crate) struct EventStreamHeaderExtensionV2 {
    pub(crate) time_mode: TimeMode,
}
impl HeaderExtension for EventStreamHeaderExtensionV2 {}

impl EventStreamHeader {
    pub(crate) fn new(
        magic: Magic,
        plane_size: PlaneSize,
        tps: u32,
        ref_interval: u32,
        delta_t_max: u32,
        codec_version: u8,
    ) -> EventStreamHeader {
        assert!(plane_size.channels > 0);
        assert!(delta_t_max > 0);
        assert!(plane_size.width > 0);
        assert!(plane_size.height > 0);
        assert!(magic == MAGIC_RAW || magic == MAGIC_COMPRESSED);

        EventStreamHeader {
            magic,
            version: codec_version,
            endianness: 98, // 'b' in ASCII, for big-endian
            width: plane_size.width,
            height: plane_size.height,
            tps,
            ref_interval,
            delta_t_max,

            // Number of bytes each event occupies
            event_size: match plane_size.channels {
                1 => 9, // If single-channel, don't need to waste 2 bytes on the c portion
                // for every event
                _ => 11,
            },
            channels: plane_size.channels,
        }
    }
}