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}