adder_codec_core/codec/
mod.rs

1#![warn(missing_docs)]
2
3use crate::codec::header::Magic;
4use crate::{DeltaT, Event, PlaneSize, SourceCamera, TimeMode};
5use bitstream_io::{BigEndian, BitReader};
6use enum_dispatch::enum_dispatch;
7use std::io;
8use std::io::{Read, Seek, Sink, Write};
9
10/// Different options for what to with the events we're given
11#[enum_dispatch(WriteCompression<W>)]
12pub enum WriteCompressionEnum<W: Write + std::marker::Send + std::marker::Sync + 'static> {
13    /// Perform (possibly lossy) compression on the ADΔER stream, and arithmetic coding
14    #[cfg(feature = "compression")]
15    CompressedOutput(CompressedOutput<W>),
16
17    /// Write the ADΔER stream as raw events
18    RawOutput(RawOutput<W>),
19
20    /// An empty output stream. Send all the data into the void.
21    EmptyOutput(EmptyOutput<Sink>),
22}
23
24/// The encoder type, along with any associated options
25#[derive(Default, Clone, Copy, PartialEq, Debug)]
26pub enum EncoderType {
27    /// Perform (possibly lossy) compression on the ADΔER stream, and arithmetic coding
28    Compressed,
29
30    /// Write the ADΔER stream as raw events
31    Raw,
32
33    // /// Write the ADΔER stream as raw events, but make sure that they are ordered perfectly according
34    // /// to their firing times
35    // RawInterleaved,
36    // RawBandwidthLimited {
37    //     target_event_rate: f64,
38    //     alpha: f64,
39    // },
40    /// Do not write any data to the output stream
41    #[default]
42    Empty,
43}
44
45#[enum_dispatch(ReadCompression<R>)]
46enum ReadCompressionEnum<R: Read + Seek> {
47    #[cfg(feature = "compression")]
48    CompressedInput(CompressedInput<R>),
49    RawInput(RawInput<R>),
50}
51
52/// Compressed codec utilities
53#[cfg(feature = "compression")]
54pub mod compressed;
55
56/// ADΔER stream decoder
57pub mod decoder;
58
59/// Filler for when generated ADΔER events need not be captured
60pub mod empty;
61
62/// ADΔER stream encoder
63pub mod encoder;
64mod header;
65
66/// Control the quality of ADDER transcoding and compression in a predictable manner
67pub mod rate_controller;
68/// Raw codec utilities
69pub mod raw;
70
71/// Current latest version of the codec.
72///
73/// This is the version which will be written to the header.
74pub const LATEST_CODEC_VERSION: u8 = 3;
75
76/// The metadata which stays the same over the course of an ADΔER stream
77#[allow(missing_docs)]
78#[derive(Copy, Clone, Debug)]
79pub struct CodecMetadata {
80    pub codec_version: u8,
81    pub header_size: usize,
82    pub time_mode: TimeMode,
83    pub plane: PlaneSize,
84    pub tps: DeltaT,
85    pub ref_interval: DeltaT,
86    pub delta_t_max: DeltaT,
87    pub event_size: u8,
88    pub source_camera: SourceCamera,
89    pub adu_interval: usize, // TODO: Allow the adu_interval to be non-constant. Each ADU will encode its own size at its beginning
90}
91
92impl Default for CodecMetadata {
93    fn default() -> Self {
94        Self {
95            codec_version: LATEST_CODEC_VERSION,
96            header_size: 24,
97            time_mode: Default::default(),
98            plane: Default::default(),
99            tps: 2550,
100            ref_interval: 255,
101            delta_t_max: 255,
102            event_size: 9,
103            source_camera: Default::default(),
104            adu_interval: 1,
105        }
106    }
107}
108
109/// A trait for writing ADΔER data to a stream.
110#[enum_dispatch]
111pub trait WriteCompression<W: Write + std::marker::Send + std::marker::Sync + 'static> {
112    // /// A struct implementing `WriteCompression` should take ownership of the `writer`.
113    // fn new(meta: CodecMetadata, writer: W) -> Self
114    // where
115    //     Self: Sized;
116
117    /// The magic number for this compression format.
118    fn magic(&self) -> Magic;
119
120    /// Returns a reference to the metadata
121    fn meta(&self) -> &CodecMetadata;
122
123    /// Returns a mutable reference to the metadata
124    fn meta_mut(&mut self) -> &mut CodecMetadata;
125
126    // fn stream(&mut self) -> &mut W;
127
128    /// Write the given bytes to the stream
129    fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
130
131    /// Align the bitstream to the next byte boundary
132    fn byte_align(&mut self) -> io::Result<()>;
133
134    /// Consumes the compression stream and returns the underlying writer.
135    fn into_writer(self) -> Option<W>;
136
137    /// Flush the `BitWriter`. Does not flush the internal `BufWriter`.
138    fn flush_writer(&mut self) -> io::Result<()>;
139
140    /// Take in an event and process it. May or may not write to the output, depending on the state
141    /// of the stream (Is it ready to write events? Is it accumulating/reorganizing events? etc.)
142    fn ingest_event(&mut self, event: Event) -> Result<(), CodecError>;
143
144    // #[cfg(feature = "compression")]
145    // fn ingest_event_debug(&mut self, event: Event) -> Result<Option<Adu>, CodecError>;
146}
147
148/// A trait for reading ADΔER data from a stream.
149///
150/// A struct implementing `ReadCompression` does not take ownership of the read handle.
151/// Subsequent calls to the compressor will pass the read handle each time. The caller is
152/// responsible for maintaining the reader.
153#[enum_dispatch]
154pub trait ReadCompression<R: Read> {
155    // fn new() -> Self
156    // where
157    //     Self: Sized;
158
159    /// Returns the magic number for the codec
160    fn magic(&self) -> Magic;
161
162    /// Returns a reference to the metadata
163    fn meta(&self) -> &CodecMetadata;
164
165    /// Returns a mutable reference to the metadata
166    fn meta_mut(&mut self) -> &mut CodecMetadata;
167
168    /// Read a certain number of bytes from the stream, indicated by the size of the buffer passed.
169    fn read_bytes(
170        &mut self,
171        bytes: &mut [u8],
172        reader: &mut BitReader<R, BigEndian>,
173    ) -> io::Result<()>;
174    // fn into_reader(self: Box<Self>, reader: &mut BitReader<R, BigEndian>) -> R;
175
176    /// Read the next event from the stream. Returns `None` if the stream is exhausted.
177    fn digest_event(&mut self, reader: &mut BitReader<R, BigEndian>) -> Result<Event, CodecError>;
178
179    // #[cfg(feature = "compression")]
180    // fn digest_event_debug(
181    //     &mut self,
182    //     reader: &mut BitReader<R, BigEndian>,
183    // ) -> Result<(Option<Adu>, Event), CodecError>;
184
185    /// Set the input stream position to the given byte offset.
186    fn set_input_stream_position(
187        &mut self,
188        reader: &mut BitReader<R, BigEndian>,
189        position: u64,
190    ) -> Result<(), CodecError>;
191
192    // fn byte_align(&mut self) -> io::Result<()>;
193
194    // fn decompress(&self, data: &[u8]) -> Vec<u8>;
195}
196
197// unsafe impl<R: Read> Send for ReadCompression {}
198// #[cfg(feature = "compression")]
199// use crate::codec::compressed::adu::frame::Adu;
200#[cfg(feature = "compression")]
201use crate::codec::compressed::stream::{CompressedInput, CompressedOutput};
202use crate::codec::empty::stream::EmptyOutput;
203use crate::codec::rate_controller::Crf;
204use crate::codec::raw::stream::{RawInput, RawOutput};
205use thiserror::Error;
206
207#[allow(missing_docs)]
208#[derive(Error, Debug)]
209pub enum CodecError {
210    #[error("stream has not been initialized")]
211    UnitializedStream,
212
213    #[error("Reached end of file when expected")]
214    Eof,
215
216    #[error("Could not deserialize data. EOF reached at unexpected time.")]
217    Deserialize,
218
219    #[error("File formatted incorrectly")]
220    BadFile,
221
222    #[error("File is of unexpected type (compressed or raw)")]
223    WrongMagic,
224
225    #[error("Attempted to seek to a bad position in the stream")]
226    Seek,
227
228    #[error("Unsupported codec version (expected {LATEST_CODEC_VERSION} or lower, found {0})")]
229    UnsupportedVersion(u8),
230
231    #[error("Malformed encoder")]
232    MalformedEncoder,
233
234    #[error("Bincode error")]
235    BincodeError(#[from] bincode::Error),
236
237    #[error("IO error")]
238    IoError(#[from] io::Error),
239
240    #[error("Plane error")]
241    PlaneError(#[from] crate::PlaneError),
242
243    // #[cfg(feature = "compression")]
244    // #[error("Blocking error")]
245    // BlockError(#[from] crate::codec::compressed::blocks::block::BlockError),
246    #[cfg(feature = "compression")]
247    #[error("Arithmetic coding error")]
248    ArithmeticCodingError(#[from] arithmetic_coding_adder_dep::Error),
249
250    /// Vision application error
251    #[error("Vision application error")]
252    VisionError(String),
253
254    #[error("No more events to read")]
255    NoMoreEvents,
256}
257
258/*
259Encoder options below
260 */
261
262/// Options related to encoder controls (what gets encoded and how)
263/// TODO: Move adu_interval into this, rather than be fixed for the whole compressed file
264#[derive(Copy, Clone, PartialEq, Debug)]
265pub struct EncoderOptions {
266    /// Allow the encoder to randomly drop events before compressing, if the event rate is too high
267    pub event_drop: EventDrop,
268
269    /// Reorder the events according to their firing times
270    pub event_order: EventOrder,
271
272    pub crf: Crf,
273}
274
275impl EncoderOptions {
276    pub fn default(plane: PlaneSize) -> Self {
277        Self {
278            event_drop: Default::default(),
279            event_order: Default::default(),
280            crf: Crf::new(None, plane),
281        }
282    }
283}
284
285/// Allow the encoder to randomly drop events before compressing, if the event rate is too high
286#[derive(Default, Copy, Clone, PartialEq, Debug)]
287pub enum EventDrop {
288    /// Don't drop any events
289    #[default]
290    None,
291
292    /// Randomly drop events according to this user-provided event rate
293    Manual {
294        target_event_rate: f64,
295
296        /// The decay rate in [0., 1.]
297        alpha: f64,
298    },
299
300    /// TODO: Implement this. Query the actual network bandwidth accoring to some stream handle
301    /// and drop events accordingly.
302    Auto,
303}
304
305/// Reorder the events according to their firing times
306#[derive(Default, Copy, Clone, PartialEq, Debug)]
307pub enum EventOrder {
308    /// Pass on the events in the order they're received in
309    #[default]
310    Unchanged,
311
312    /// Reorder the events according to their firing times
313    Interleaved,
314}