Skip to content

Commit 9edc15e

Browse files
ac-freemandaniel.eadesclaude
authored
Cleanup (#137)
* refactor!: use upstream arithmetic-coding library * Clean up dead code, fix broken bench, and trim hot-path overhead Fix the workspace build (framed_to_adder_hd.rs bench used removed Framed/SimulProcArgs/SimulProcessor APIs from the arithmetic-coding refactor). Remove dead code surfaced by clippy: the entirely-unused d_controller module, ~390 lines of commented-out Bevy-era UI in adder-viz, unused struct fields/test helpers, and panic/todo! trait impls kept only to satisfy bounds. Fix clippy warnings (unused vars/imports, swallowed Results, a vec![x; n] pattern that silently dropped Vec capacity) and strip stray dbg!/eprintln! debug leftovers, including one firing every frame in a hot path. Performance: replace a linear D_SHIFT scan in the per-event pixel integration path with a leading_zeros()-based bit-length lookup, preallocate a 3D pixel buffer instead of growing it via nested push(), and write DVS text events directly instead of building an intermediate String per event. All existing tests pass; cargo fmt and clippy are clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix busy loop * Update adder.rs --------- Co-authored-by: daniel.eades <daniel.eades@seebyte.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0ceabd1 commit 9edc15e

85 files changed

Lines changed: 673 additions & 17296 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.idea/runConfigurations/Test_stable.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adder-codec-core/Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ exclude = [
1818

1919
[features]
2020
default = ["compression"]
21-
compression = ["dep:arithmetic-coding-adder-dep"]
21+
compression = ["dep:arithmetic-coding"]
2222

2323
[dependencies]
24-
arithmetic-coding-adder-dep = { path = "../arithmetic-coding-adder-dep", version = "0.3.3", optional = true }
25-
#arithmetic-coding-adder-dep = { version = "0.3.1", optional = true }
24+
arithmetic-coding = { version = "0.4.0", optional = true }
2625
bincode = "1.3.3"
27-
bitstream-io = "2.5.3"
26+
bitstream-io = "2.6.0"
2827
enum_dispatch = "0.3.11"
2928
fenwick = "2.0.1"
3029
float-cmp = "0.9.0"

adder-codec-core/src/codec/compressed/fenwick/context_switching.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// From https://github.com/danieleades/arithmetic-coding. Only temporary, for initial testing.
22
//! Fenwick tree based context-switching model
33
4-
use arithmetic_coding_adder_dep::Model;
4+
use arithmetic_coding::Model;
55

66
use super::Weights;
77
use crate::codec::compressed::fenwick::ValueError;
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
use crate::codec::compressed::fenwick::context_switching::FenwickModel;
2+
use crate::codec::compressed::source_model::cabac_contexts::{
3+
Contexts, BITSHIFT_ENCODE_FULL, D_RESIDUAL_OFFSET,
4+
};
5+
use crate::codec::compressed::{DResidual, TResidual, DRESIDUAL_NO_EVENT, DRESIDUAL_SKIP_CUBE};
6+
use crate::{AbsoluteT, DeltaT};
7+
use arithmetic_coding::Model;
8+
use std::mem::size_of;
9+
10+
const D_RESIDUAL_BYTES: usize = size_of::<DResidual>();
11+
12+
#[derive(Debug, Clone)]
13+
enum Phase {
14+
Header {
15+
bytes_remaining: usize,
16+
},
17+
IntraD,
18+
IntraBitshift,
19+
IntraT {
20+
bytes_remaining: usize,
21+
},
22+
InterD {
23+
bytes_remaining: usize,
24+
d_buf: [u8; 2],
25+
},
26+
InterBitshift,
27+
InterT {
28+
bytes_remaining: usize,
29+
},
30+
Eof,
31+
}
32+
33+
impl Phase {
34+
fn context(&self, contexts: &Contexts) -> usize {
35+
match self {
36+
Phase::Header { .. } | Phase::IntraT { .. } | Phase::InterT { .. } => {
37+
contexts.t_context
38+
}
39+
Phase::IntraD | Phase::InterD { .. } => contexts.d_context,
40+
Phase::IntraBitshift | Phase::InterBitshift => contexts.bitshift_context,
41+
Phase::Eof => contexts.eof_context,
42+
}
43+
}
44+
}
45+
46+
#[derive(Debug)]
47+
pub struct FacadeModel {
48+
inner: FenwickModel,
49+
contexts: Contexts,
50+
phase: Phase,
51+
}
52+
53+
impl FacadeModel {
54+
#[must_use]
55+
pub fn new(dt_ref: DeltaT, max_denominator: u64) -> Self {
56+
let mut inner = FenwickModel::with_symbols(u16::MAX as usize, max_denominator);
57+
let contexts = Contexts::new(&mut inner, dt_ref);
58+
let phase = Phase::Header {
59+
bytes_remaining: size_of::<AbsoluteT>(),
60+
};
61+
let mut model = Self {
62+
inner,
63+
contexts,
64+
phase,
65+
};
66+
model.inner.set_context(model.contexts.t_context);
67+
model
68+
}
69+
70+
pub fn contexts(&self) -> &Contexts {
71+
&self.contexts
72+
}
73+
74+
pub fn begin_intra(&mut self) {
75+
self.phase = Phase::IntraD;
76+
self.inner.set_context(self.contexts.d_context);
77+
}
78+
79+
pub fn begin_inter(&mut self) {
80+
self.phase = Phase::InterD {
81+
bytes_remaining: D_RESIDUAL_BYTES,
82+
d_buf: [0; 2],
83+
};
84+
self.inner.set_context(self.contexts.d_context);
85+
}
86+
87+
pub fn begin_eof(&mut self) {
88+
self.phase = Phase::Eof;
89+
self.inner.set_context(self.contexts.eof_context);
90+
}
91+
92+
fn advance_phase(&mut self, symbol: Option<&usize>) {
93+
let symbol = symbol.copied();
94+
let phase = std::mem::replace(&mut self.phase, Phase::Eof);
95+
let next_phase = match phase {
96+
Phase::Header {
97+
mut bytes_remaining,
98+
} => {
99+
bytes_remaining = bytes_remaining.saturating_sub(1);
100+
Phase::Header { bytes_remaining }
101+
}
102+
Phase::IntraD => match symbol {
103+
Some(value) => {
104+
let no_event = (DRESIDUAL_NO_EVENT + D_RESIDUAL_OFFSET) as usize;
105+
let skip = (DRESIDUAL_SKIP_CUBE + D_RESIDUAL_OFFSET) as usize;
106+
if value == no_event || value == skip {
107+
Phase::IntraD
108+
} else {
109+
Phase::IntraBitshift
110+
}
111+
}
112+
None => Phase::IntraD,
113+
},
114+
Phase::IntraBitshift => match symbol {
115+
Some(value) => Phase::IntraT {
116+
bytes_remaining: t_residual_bytes(value),
117+
},
118+
None => Phase::IntraBitshift,
119+
},
120+
Phase::IntraT {
121+
mut bytes_remaining,
122+
} => {
123+
bytes_remaining = bytes_remaining.saturating_sub(1);
124+
if bytes_remaining == 0 {
125+
Phase::IntraD
126+
} else {
127+
Phase::IntraT { bytes_remaining }
128+
}
129+
}
130+
Phase::InterD {
131+
mut bytes_remaining,
132+
mut d_buf,
133+
} => match symbol {
134+
Some(value) => {
135+
let byte = value as u8;
136+
if bytes_remaining == D_RESIDUAL_BYTES {
137+
d_buf[0] = byte;
138+
bytes_remaining -= 1;
139+
Phase::InterD {
140+
bytes_remaining,
141+
d_buf,
142+
}
143+
} else {
144+
d_buf[1] = byte;
145+
let d_residual = DResidual::from_be_bytes(d_buf);
146+
if d_residual == DRESIDUAL_NO_EVENT {
147+
Phase::InterD {
148+
bytes_remaining: D_RESIDUAL_BYTES,
149+
d_buf: [0; 2],
150+
}
151+
} else {
152+
Phase::InterBitshift
153+
}
154+
}
155+
}
156+
None => Phase::InterD {
157+
bytes_remaining,
158+
d_buf,
159+
},
160+
},
161+
Phase::InterBitshift => match symbol {
162+
Some(value) => Phase::InterT {
163+
bytes_remaining: t_residual_bytes(value),
164+
},
165+
None => Phase::InterBitshift,
166+
},
167+
Phase::InterT {
168+
mut bytes_remaining,
169+
} => {
170+
bytes_remaining = bytes_remaining.saturating_sub(1);
171+
if bytes_remaining == 0 {
172+
Phase::InterD {
173+
bytes_remaining: D_RESIDUAL_BYTES,
174+
d_buf: [0; 2],
175+
}
176+
} else {
177+
Phase::InterT { bytes_remaining }
178+
}
179+
}
180+
Phase::Eof => Phase::Eof,
181+
};
182+
self.phase = next_phase;
183+
let context = self.phase.context(&self.contexts);
184+
self.inner.set_context(context);
185+
}
186+
}
187+
188+
impl Model for FacadeModel {
189+
type B = u64;
190+
type Symbol = usize;
191+
type ValueError = crate::codec::compressed::fenwick::ValueError;
192+
193+
fn probability(
194+
&self,
195+
symbol: Option<&Self::Symbol>,
196+
) -> Result<std::ops::Range<Self::B>, Self::ValueError> {
197+
self.inner.probability(symbol)
198+
}
199+
200+
fn denominator(&self) -> Self::B {
201+
self.inner.denominator()
202+
}
203+
204+
fn max_denominator(&self) -> Self::B {
205+
self.inner.max_denominator()
206+
}
207+
208+
fn symbol(&self, value: Self::B) -> Option<Self::Symbol> {
209+
self.inner.symbol(value)
210+
}
211+
212+
fn update(&mut self, symbol: Option<&Self::Symbol>) {
213+
self.inner.update(symbol);
214+
self.advance_phase(symbol);
215+
}
216+
}
217+
218+
fn t_residual_bytes(bitshift_value: usize) -> usize {
219+
if bitshift_value as u8 == BITSHIFT_ENCODE_FULL {
220+
size_of::<i64>()
221+
} else {
222+
size_of::<TResidual>()
223+
}
224+
}

adder-codec-core/src/codec/compressed/fenwick/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use std::ops::Range;
55

66
pub mod context_switching;
7+
pub mod facade;
78
pub mod simple;
89

910
/// A wrapper around a vector of fenwick counts, with one additional weight for

adder-codec-core/src/codec/compressed/fenwick/simple.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![allow(missing_docs, unused)]
33
//! simple adaptive model using a fenwick tree
44
5-
use arithmetic_coding_adder_dep::Model;
5+
use arithmetic_coding::Model;
66

77
use super::Weights;
88
use crate::codec::compressed::fenwick::ValueError;

adder-codec-core/src/codec/compressed/source_model/cabac_contexts.rs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use crate::codec::compressed::fenwick::context_switching::FenwickModel;
22
use crate::codec::compressed::fenwick::Weights;
33
use crate::{AbsoluteT, DeltaT, EventCoordless, Intensity, D, D_SHIFT};
4-
use arithmetic_coding_adder_dep::Encoder;
5-
use bitstream_io::{BigEndian, BitWrite, BitWriter};
64

5+
#[derive(Clone, Debug)]
76
pub struct Contexts {
87
/// Decimation factor residuals context
98
pub(crate) d_context: usize,
@@ -224,16 +223,4 @@ pub fn d_residual_default_weights() -> Weights {
224223
Weights::new_with_counts(counts.len(), &Vec::from(counts))
225224
}
226225

227-
pub fn eof_context(
228-
contexts: &Contexts,
229-
encoder: &mut Encoder<FenwickModel, BitWriter<Vec<u8>, BigEndian>>,
230-
stream: &mut BitWriter<Vec<u8>, BigEndian>,
231-
) {
232-
// THIS IS CRUCIAL FOR TESTING
233-
let eof_context = contexts.eof_context;
234-
encoder.model.set_context(eof_context);
235-
encoder.encode(None, stream).unwrap();
236-
encoder.flush(stream).unwrap();
237-
stream.byte_align().unwrap();
238-
stream.flush().unwrap();
239-
}
226+
// EOF handling is done by the facade model and top-level encoder flow.

0 commit comments

Comments
 (0)