Bink Video encoder (only 'b' version for now)
[nihav.git] / nihav-rad / src / codecs / binkvidenc / bundle.rs
CommitLineData
217de10b
KS
1use std::collections::VecDeque;
2use nihav_core::io::bitwriter::*;
3
4const BUNDLE_LEN_BITS: u8 = 13;
5const MAX_BUNDLE_LEN: usize = 1 << BUNDLE_LEN_BITS;
6
7#[derive(Default)]
8struct Bundle<T:Copy> {
9 bits: u8,
10 data: VecDeque<(usize, Vec<T>)>,
11 row: usize,
12 tmp: Vec<T>,
13 end: bool,
14 last_w: usize,
15}
16
17impl<T:Copy> Bundle<T> {
18 fn reset(&mut self, bits: u8) {
19 self.bits = bits;
20 self.end = false;
21 self.last_w = 0;
22 }
23 fn new_row(&mut self, row: usize) {
24 self.row = row;
25 }
26 fn push(&mut self, val: T) {
27 self.tmp.push(val);
28 }
29 fn push_all(&mut self, slc: &[T]) {
30 self.tmp.extend_from_slice(slc);
31 }
32 fn end_row(&mut self) {
33 if !self.tmp.is_empty() {
34 let mut tmp = Vec::new();
35 std::mem::swap(&mut tmp, &mut self.tmp);
36 self.data.push_back((self.row, tmp));
37 }
38 }
39}
40
41trait IntoU32 {
42 fn into_u32(self) -> u32;
43}
44
45impl IntoU32 for u8 {
46 fn into_u32(self) -> u32 { u32::from(self) }
47}
48
49impl IntoU32 for i8 {
50 fn into_u32(self) -> u32 { (self + 16) as u32 }
51}
52
53impl IntoU32 for u16 {
54 fn into_u32(self) -> u32 { u32::from(self) }
55}
56
57impl IntoU32 for i16 {
58 fn into_u32(self) -> u32 { (self + 1024) as u32 }
59}
60
61impl Bundle<(u16, u8)> {
62 fn write(&mut self, bw: &mut BitWriter, cur_row: usize) {
63 if !self.data.is_empty() && self.data[0].0 == cur_row {
64 let (_, row_data) = self.data.pop_front().unwrap();
65 for &(bits, len) in row_data.iter() {
66 bw.write(u32::from(bits), len);
67 }
68 }
69 }
70}
71
72impl<T: Copy+IntoU32> Bundle<T> {
73 fn write(&mut self, bw: &mut BitWriter, cur_row: usize) {
74 if !self.end && cur_row == self.last_w {
75 let mut num_out = 0;
76 let mut len_out = 0;
77 for (_, row) in self.data.iter() {
78 if len_out + row.len() < MAX_BUNDLE_LEN {
79 len_out += row.len();
80 num_out += 1;
81 } else {
82 break;
83 }
84 }
85
86 bw.write(len_out as u32, BUNDLE_LEN_BITS);
87 if len_out == 0 {
88 self.end = true;
89 return;
90 }
91 for _ in 0..num_out {
92 let (row_no, row_data) = self.data.pop_front().unwrap();
93 self.last_w = row_no + 1;
94 for &el in row_data.iter() {
95 bw.write(el.into_u32(), self.bits);
96 }
97 }
98 }
99 }
100}
101
102#[derive(Default)]
103pub struct Bundles {
104 btype: Bundle<u8>,
105 colors: Bundle<u8>,
106 pattern: Bundle<u8>,
107 xoff: Bundle<i8>,
108 yoff: Bundle<i8>,
109 intradc: Bundle<u16>,
110 interdc: Bundle<i16>,
111 intraq: Bundle<u8>,
112 interq: Bundle<u8>,
113 nresidues: Bundle<u8>,
114 other: Bundle<(u16, u8)>,
115}
116
117macro_rules! whole_bundle {
118 ($self:expr, $func:ident) => {
119 $self.btype.$func();
120 $self.colors.$func();
121 $self.pattern.$func();
122 $self.xoff.$func();
123 $self.yoff.$func();
124 $self.intradc.$func();
125 $self.interdc.$func();
126 $self.intraq.$func();
127 $self.interq.$func();
128 $self.nresidues.$func();
129 $self.other.$func();
130 };
131 ($self:expr, $func:ident, $($args:expr),*) => {
132 $self.btype.$func($($args),*);
133 $self.colors.$func($($args),*);
134 $self.pattern.$func($($args),*);
135 $self.xoff.$func($($args),*);
136 $self.yoff.$func($($args),*);
137 $self.intradc.$func($($args),*);
138 $self.interdc.$func($($args),*);
139 $self.intraq.$func($($args),*);
140 $self.interq.$func($($args),*);
141 $self.nresidues.$func($($args),*);
142 $self.other.$func($($args),*);
143 }
144}
145
146impl Bundles {
147 pub fn reset(&mut self) {
148 self.btype.reset(4);
149 self.colors.reset(8);
150 self.pattern.reset(8);
151 self.xoff.reset(5);
152 self.yoff.reset(5);
153 self.intradc.reset(11);
154 self.interdc.reset(11);
155 self.intraq.reset(4);
156 self.interq.reset(4);
157 self.nresidues.reset(7);
158 }
159 pub fn add_block_type(&mut self, btype: u8) {
160 self.btype.push(btype);
161 }
162 pub fn write(&mut self, bw: &mut BitWriter, row: usize) {
163 whole_bundle!(self, write, bw, row);
164 }
165 pub fn new_row(&mut self, row: usize) {
166 whole_bundle!(self, new_row, row);
167 }
168 pub fn end_row(&mut self) {
169 whole_bundle!(self, end_row);
170 }
171
172 pub fn can_fit_raw_block(&self) -> bool {
173 self.colors.data.len() < MAX_BUNDLE_LEN - 1 - 64
174 }
175 pub fn add_tokens(&mut self, tokens: &BlockTokens) {
176 self.colors.push_all(&tokens.colors);
177 self.pattern.push_all(&tokens.pattern);
178 self.xoff.push_all(&tokens.xoff);
179 self.yoff.push_all(&tokens.yoff);
180 self.intradc.push_all(&tokens.intradc);
181 self.interdc.push_all(&tokens.interdc);
182 self.intraq.push_all(&tokens.intraq);
183 self.interq.push_all(&tokens.interq);
184 self.nresidues.push_all(&tokens.nresidues);
185 self.other.push_all(&tokens.other);
186 }
187}
188
189#[derive(Default)]
190pub struct BlockTokens {
191 pub colors: Vec<u8>,
192 pub pattern: Vec<u8>,
193 pub xoff: Vec<i8>,
194 pub yoff: Vec<i8>,
195 pub intradc: Vec<u16>,
196 pub interdc: Vec<i16>,
197 pub intraq: Vec<u8>,
198 pub interq: Vec<u8>,
199 pub nresidues: Vec<u8>,
200 pub other: Vec<(u16, u8)>,
201}
202
203impl BlockTokens {
204 pub fn new() -> Self { Self::default() }
205 pub fn clear(&mut self) {
206 self.colors.clear();
207 self.pattern.clear();
208 self.xoff.clear();
209 self.yoff.clear();
210 self.intradc.clear();
211 self.interdc.clear();
212 self.intraq.clear();
213 self.interq.clear();
214 self.nresidues.clear();
215 self.other.clear();
216 }
217 pub fn bits(&self, is_b: bool) -> usize {
218 if is_b {
219 self.colors.len() * 8 +
220 self.pattern.len() * 8 +
221 self.xoff.len() * 5 +
222 self.yoff.len() * 5 +
223 self.intradc.len() * 11 +
224 self.interdc.len() * 11 +
225 self.intraq.len() * 4 +
226 self.interq.len() * 4 +
227 self.nresidues.len() * 7 +
228 self.other.iter().fold(0usize, |acc, &(_, len)| acc + usize::from(len))
229 } else {
230unimplemented!()
231 }
232 }
233}