atmos/os_lib/
h264_cabac.rs1use super::h264_cabac_tables::{CABAC_INIT_I, CABAC_INIT_PB, CTX_COUNT, RANGE_TAB_LPS, TRANS_IDX_LPS};
8
9pub struct CabacEngine<'a> {
11 data: &'a [u8],
12 pos: usize,
14 range: u32,
15 offset: u32,
16 state: [u8; CTX_COUNT],
18}
19
20impl<'a> CabacEngine<'a> {
21 pub fn new(data: &'a [u8], bit_pos: usize, slice_qp: i32, cabac_init_idc: Option<u32>) -> Self {
24 let table = match cabac_init_idc {
25 None => &CABAC_INIT_I,
26 Some(i) => &CABAC_INIT_PB[(i as usize).min(2)],
27 };
28 let qp = slice_qp.clamp(0, 51);
29 let mut state = [0u8; CTX_COUNT];
30 for (s, &(m, n)) in state.iter_mut().zip(table.iter()) {
31 let pre = (((m as i32 * qp) >> 4) + n as i32).clamp(1, 126);
33 *s = if pre <= 63 { ((63 - pre) << 1) as u8 } else { (((pre - 64) << 1) | 1) as u8 };
34 }
35 let mut e = Self { data, pos: (bit_pos + 7) & !7, range: 510, offset: 0, state };
36 e.init_engine();
37 e
38 }
39
40 fn init_engine(&mut self) {
42 self.range = 510;
43 self.offset = 0;
44 for _ in 0..9 {
45 self.offset = (self.offset << 1) | self.bit();
46 }
47 }
48
49 fn bit(&mut self) -> u32 {
50 let b = self.data.get(self.pos / 8).map_or(0, |&b| (b >> (7 - (self.pos % 8))) & 1);
51 self.pos += 1;
52 b as u32
53 }
54
55 pub fn decision(&mut self, ctx: usize) -> u32 {
57 let Some(&s) = self.state.get(ctx) else { return 0 };
58 let p = (s >> 1) as usize;
59 let mps = (s & 1) as u32;
60 let lps = RANGE_TAB_LPS[p][((self.range >> 6) & 3) as usize] as u32;
61 self.range -= lps;
62 let bin;
63 if self.offset >= self.range {
64 bin = 1 - mps;
65 self.offset -= self.range;
66 self.range = lps;
67 let new_mps = if p == 0 { 1 - mps } else { mps };
68 self.state[ctx] = (TRANS_IDX_LPS[p] << 1) | new_mps as u8;
69 } else {
70 bin = mps;
71 let np = if p < 62 { p + 1 } else { p };
72 self.state[ctx] = ((np as u8) << 1) | mps as u8;
73 }
74 while self.range < 256 {
75 self.range <<= 1;
76 self.offset = (self.offset << 1) | self.bit();
77 }
78 bin
79 }
80
81 pub fn bypass(&mut self) -> u32 {
83 self.offset = (self.offset << 1) | self.bit();
84 if self.offset >= self.range {
85 self.offset -= self.range;
86 1
87 } else {
88 0
89 }
90 }
91
92 pub fn terminate(&mut self) -> u32 {
94 self.range -= 2;
95 if self.offset >= self.range {
96 1
97 } else {
98 while self.range < 256 {
99 self.range <<= 1;
100 self.offset = (self.offset << 1) | self.bit();
101 }
102 0
103 }
104 }
105
106 pub fn read_pcm(&mut self, out: &mut [u8]) {
108 self.pos = (self.pos + 7) & !7;
109 for o in out.iter_mut() {
110 *o = self.data.get(self.pos / 8).copied().unwrap_or(0);
111 self.pos += 8;
112 }
113 self.init_engine();
114 }
115}