]>
Commit | Line | Data |
---|---|---|
1 | use nihav_codec_support::codecs::ZIGZAG; | |
2 | use super::super::vp6data::*; | |
3 | ||
4 | #[derive(Clone,Copy,Default)] | |
5 | pub struct VP56MVModel { | |
6 | pub nz_prob: u8, | |
7 | pub sign_prob: u8, | |
8 | pub raw_probs: [u8; 8], | |
9 | pub tree_probs: [u8; 7], | |
10 | } | |
11 | ||
12 | #[derive(Clone,Copy,Default)] | |
13 | pub struct VP56MBTypeModel { | |
14 | pub probs: [u8; 10], | |
15 | } | |
16 | ||
17 | #[derive(Clone,Copy,Default)] | |
18 | pub struct VP56CoeffModel { | |
19 | pub dc_token_probs: [[[u8; 5]; 6]; 6], | |
20 | pub dc_value_probs: [u8; 11], | |
21 | pub ac_val_probs: [[[u8; 11]; 6]; 3], | |
22 | } | |
23 | ||
24 | #[derive(Clone)] | |
25 | pub struct VP6Models { | |
26 | pub scan_order: [usize; 64], | |
27 | pub scan: [usize; 64], | |
28 | pub zigzag: [usize; 64], | |
29 | pub zero_run_probs: [[u8; 14]; 2], | |
30 | } | |
31 | ||
32 | const MAX_HUFF_ELEMS: usize = 12; | |
33 | #[derive(Clone,Copy,Default)] | |
34 | pub struct VP6Huff { | |
35 | pub codes: [u16; MAX_HUFF_ELEMS], | |
36 | pub bits: [u8; MAX_HUFF_ELEMS], | |
37 | } | |
38 | ||
39 | #[derive(Clone,Copy,Default)] | |
40 | struct Node { | |
41 | weight: u16, | |
42 | sym: i8, | |
43 | ch0: usize, | |
44 | ch1: usize, | |
45 | } | |
46 | ||
47 | fn prob2weight(a: u8, b: u8) -> u8 { | |
48 | let w = ((u16::from(a) * u16::from(b)) >> 8) as u8; | |
49 | if w == 0 { | |
50 | 1 | |
51 | } else { | |
52 | w | |
53 | } | |
54 | } | |
55 | ||
56 | impl VP6Huff { | |
57 | pub fn build_codes(&mut self, probs: &[u8; 11]) { | |
58 | let mut weights = [0u8; 12]; | |
59 | ||
60 | weights[11] = prob2weight( probs[0], probs[ 1]); | |
61 | weights[ 0] = prob2weight( probs[0], !probs[ 1]); | |
62 | weights[ 1] = prob2weight(!probs[0], probs[ 2]); | |
63 | let lvroot = prob2weight(!probs[0], !probs[ 2]); | |
64 | let tworoot = prob2weight( lvroot, probs[ 3]); | |
65 | let hlroot = prob2weight( lvroot, !probs[ 3]); | |
66 | weights[ 2] = prob2weight( tworoot, probs[ 4]); | |
67 | let root34 = prob2weight( tworoot, !probs[ 4]); | |
68 | weights[ 3] = prob2weight( root34, probs[ 5]); | |
69 | weights[ 4] = prob2weight( root34, !probs[ 5]); | |
70 | let c1root = prob2weight( hlroot, probs[ 6]); | |
71 | let c34root = prob2weight( hlroot, !probs[ 6]); | |
72 | weights[ 5] = prob2weight( c1root, probs[ 7]); | |
73 | weights[ 6] = prob2weight( c1root, !probs[ 7]); | |
74 | let c3root = prob2weight( c34root, probs[ 8]); | |
75 | let c4root = prob2weight( c34root, !probs[ 8]); | |
76 | weights[ 7] = prob2weight( c3root, probs[ 9]); | |
77 | weights[ 8] = prob2weight( c3root, !probs[ 9]); | |
78 | weights[ 9] = prob2weight( c4root, probs[10]); | |
79 | weights[10] = prob2weight( c4root, !probs[10]); | |
80 | ||
81 | self.build(&weights); | |
82 | } | |
83 | pub fn build_codes_zero_run(&mut self, probs: &[u8; 14]) { | |
84 | let mut weights = [0u8; 9]; | |
85 | ||
86 | let root = prob2weight( probs[0], probs[1]); | |
87 | weights[0] = prob2weight( root, probs[2]); | |
88 | weights[1] = prob2weight( root, !probs[2]); | |
89 | ||
90 | let root = prob2weight( probs[0], !probs[1]); | |
91 | weights[2] = prob2weight( root, probs[3]); | |
92 | weights[3] = prob2weight( root, !probs[3]); | |
93 | ||
94 | let root = prob2weight(!probs[0], probs[4]); | |
95 | weights[8] = prob2weight(!probs[0], !probs[4]); | |
96 | let root1 = prob2weight( root, probs[5]); | |
97 | let root2 = prob2weight( root, !probs[5]); | |
98 | weights[4] = prob2weight( root1, probs[6]); | |
99 | weights[5] = prob2weight( root1, !probs[6]); | |
100 | weights[6] = prob2weight( root2, probs[7]); | |
101 | weights[7] = prob2weight( root2, !probs[7]); | |
102 | ||
103 | self.build(&weights); | |
104 | } | |
105 | fn build(&mut self, weights: &[u8]) { | |
106 | let mut nodes = [Node::default(); MAX_HUFF_ELEMS * 2]; | |
107 | let mut nlen = 0; | |
108 | ||
109 | for w in weights.iter().rev() { | |
110 | let weight = u16::from(*w); | |
111 | let mut pos = nlen; | |
112 | for i in 0..nlen { | |
113 | if nodes[i].weight > weight { | |
114 | pos = i; | |
115 | break; | |
116 | } | |
117 | } | |
118 | for j in (pos..nlen).rev() { | |
119 | nodes[j + 1] = nodes[j]; | |
120 | } | |
121 | nodes[pos].weight = weight; | |
122 | nodes[pos].sym = (weights.len() - nlen - 1) as i8; | |
123 | nlen += 1; | |
124 | } | |
125 | ||
126 | let mut low = 0; | |
127 | for _ in 0..nlen-1 { | |
128 | let nnode = Node { | |
129 | weight: nodes[low + 0].weight + nodes[low + 1].weight, | |
130 | sym: -1, | |
131 | ch0: low + 0, | |
132 | ch1: low + 1, | |
133 | }; | |
134 | low += 2; | |
135 | let mut pos = low; | |
136 | while (pos < nlen) && (nodes[pos].weight < nnode.weight) { | |
137 | pos += 1; | |
138 | } | |
139 | for j in (pos..nlen).rev() { | |
140 | nodes[j + 1] = nodes[j]; | |
141 | } | |
142 | nodes[pos] = nnode; | |
143 | nlen += 1; | |
144 | } | |
145 | self.get_codes(&nodes, nlen - 1, 0, 0); | |
146 | for i in nlen..self.codes.len() { | |
147 | self.codes[i] = self.codes[0]; | |
148 | self.bits[i] = self.bits[0]; | |
149 | } | |
150 | } | |
151 | fn get_codes(&mut self, nodes: &[Node], pos: usize, code: u16, len: u8) { | |
152 | if nodes[pos].sym >= 0 { | |
153 | self.codes[nodes[pos].sym as usize] = code; | |
154 | self.bits [nodes[pos].sym as usize] = len; | |
155 | } else { | |
156 | self.get_codes(nodes, nodes[pos].ch0, (code << 1) | 0, len + 1); | |
157 | self.get_codes(nodes, nodes[pos].ch1, (code << 1) | 1, len + 1); | |
158 | } | |
159 | } | |
160 | } | |
161 | ||
162 | #[derive(Clone,Copy,Default)] | |
163 | pub struct VP6HuffModels { | |
164 | pub dc_token_tree: [VP6Huff; 2], | |
165 | pub ac_token_tree: [[[VP6Huff; 6]; 3]; 2], | |
166 | pub zero_run_tree: [VP6Huff; 2], | |
167 | } | |
168 | ||
169 | impl VP6Models { | |
170 | fn new() -> Self { | |
171 | Self { | |
172 | scan_order: [0; 64], | |
173 | scan: [0; 64], | |
174 | zigzag: [0; 64], | |
175 | zero_run_probs: [[0; 14]; 2], | |
176 | } | |
177 | } | |
178 | } | |
179 | ||
180 | #[derive(Clone)] | |
181 | pub struct VP56Models { | |
182 | pub mv_models: [VP56MVModel; 2], | |
183 | pub mbtype_models: [[VP56MBTypeModel; 10]; 3], | |
184 | pub coeff_models: [VP56CoeffModel; 2], | |
185 | pub prob_xmitted: [[u8; 20]; 3], | |
186 | pub vp6models: VP6Models, | |
187 | pub vp6huff: VP6HuffModels, | |
188 | } | |
189 | ||
190 | impl VP56Models { | |
191 | pub fn new() -> Self { | |
192 | Self { | |
193 | mv_models: [VP56MVModel::default(); 2], | |
194 | mbtype_models: [[VP56MBTypeModel::default(); 10]; 3], | |
195 | coeff_models: [VP56CoeffModel::default(); 2], | |
196 | prob_xmitted: [[0; 20]; 3], | |
197 | vp6models: VP6Models::new(), | |
198 | vp6huff: VP6HuffModels::default(), | |
199 | } | |
200 | } | |
201 | pub fn reset(&mut self, interlaced: bool) { | |
202 | for (i, mdl) in self.mv_models.iter_mut().enumerate() { | |
203 | mdl.nz_prob = NZ_PROBS[i]; | |
204 | mdl.sign_prob = 128; | |
205 | mdl.raw_probs.copy_from_slice(&RAW_PROBS[i]); | |
206 | mdl.tree_probs.copy_from_slice(&TREE_PROBS[i]); | |
207 | } | |
208 | ||
209 | for mdl in self.coeff_models.iter_mut() { | |
210 | mdl.dc_value_probs = [128; 11]; | |
211 | mdl.ac_val_probs = [[[128; 11]; 6]; 3]; | |
212 | } | |
213 | self.vp6models.zero_run_probs.copy_from_slice(&ZERO_RUN_PROBS); | |
214 | reset_scan(&mut self.vp6models, interlaced); | |
215 | } | |
216 | pub fn reset_mbtype_models(&mut self) { | |
217 | const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [ | |
218 | [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ], | |
219 | [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ], | |
220 | [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ] | |
221 | ]; | |
222 | self.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS); | |
223 | } | |
224 | } | |
225 | ||
226 | pub fn reset_scan(model: &mut VP6Models, interlaced: bool) { | |
227 | if !interlaced { | |
228 | model.scan_order.copy_from_slice(&VP6_DEFAULT_SCAN_ORDER); | |
229 | } else { | |
230 | model.scan_order.copy_from_slice(&VP6_INTERLACED_SCAN_ORDER); | |
231 | } | |
232 | for i in 0..64 { model.scan[i] = i; } | |
233 | model.zigzag.copy_from_slice(&ZIGZAG); | |
234 | } | |
235 | ||
236 | #[derive(Clone,Copy,Default)] | |
237 | pub struct ProbCounter { | |
238 | zeroes: u32, | |
239 | total: u32, | |
240 | } | |
241 | ||
242 | // bits to code zero probability multiplied by eight | |
243 | pub const PROB_BITS: [u8; 256] = [ | |
244 | 0, 64, 56, 51, 48, 45, 43, 42, | |
245 | 40, 39, 37, 36, 35, 34, 34, 33, | |
246 | 32, 31, 31, 30, 29, 29, 28, 28, | |
247 | 27, 27, 26, 26, 26, 25, 25, 24, | |
248 | 24, 24, 23, 23, 23, 22, 22, 22, | |
249 | 21, 21, 21, 21, 20, 20, 20, 20, | |
250 | 19, 19, 19, 19, 18, 18, 18, 18, | |
251 | 18, 17, 17, 17, 17, 17, 16, 16, | |
252 | 16, 16, 16, 15, 15, 15, 15, 15, | |
253 | 15, 14, 14, 14, 14, 14, 14, 14, | |
254 | 13, 13, 13, 13, 13, 13, 13, 12, | |
255 | 12, 12, 12, 12, 12, 12, 12, 11, | |
256 | 11, 11, 11, 11, 11, 11, 11, 11, | |
257 | 10, 10, 10, 10, 10, 10, 10, 10, | |
258 | 10, 9, 9, 9, 9, 9, 9, 9, | |
259 | 9, 9, 9, 8, 8, 8, 8, 8, | |
260 | 8, 8, 8, 8, 8, 8, 7, 7, | |
261 | 7, 7, 7, 7, 7, 7, 7, 7, | |
262 | 7, 7, 6, 6, 6, 6, 6, 6, | |
263 | 6, 6, 6, 6, 6, 6, 6, 5, | |
264 | 5, 5, 5, 5, 5, 5, 5, 5, | |
265 | 5, 5, 5, 5, 5, 5, 4, 4, | |
266 | 4, 4, 4, 4, 4, 4, 4, 4, | |
267 | 4, 4, 4, 4, 4, 4, 3, 3, | |
268 | 3, 3, 3, 3, 3, 3, 3, 3, | |
269 | 3, 3, 3, 3, 3, 3, 3, 2, | |
270 | 2, 2, 2, 2, 2, 2, 2, 2, | |
271 | 2, 2, 2, 2, 2, 2, 2, 2, | |
272 | 2, 1, 1, 1, 1, 1, 1, 1, | |
273 | 1, 1, 1, 1, 1, 1, 1, 1, | |
274 | 1, 1, 1, 1, 1, 1, 0, 0, | |
275 | 0, 0, 0, 0, 0, 0, 0, 0 | |
276 | ]; | |
277 | ||
278 | impl ProbCounter { | |
279 | pub fn add(&mut self, b: bool) { | |
280 | if !b { | |
281 | self.zeroes += 1; | |
282 | } | |
283 | self.total += 1; | |
284 | } | |
285 | pub fn to_prob(self) -> u8 { | |
286 | if self.total > 0 { | |
287 | (((self.zeroes << 8) / self.total).min(254) & !1).max(1) as u8 | |
288 | } else { | |
289 | 128 | |
290 | } | |
291 | } | |
292 | pub fn to_prob_worthy(&self, old_prob: u8) -> u8 { | |
293 | if self.total > 0 { | |
294 | let new_prob = self.to_prob(); | |
295 | let new_bits = Self::est_bits(new_prob, self.zeroes, self.total); | |
296 | let old_bits = Self::est_bits(old_prob, self.zeroes, self.total); | |
297 | ||
298 | if new_bits + 7 < old_bits { | |
299 | new_prob | |
300 | } else { | |
301 | old_prob | |
302 | } | |
303 | } else { | |
304 | old_prob | |
305 | } | |
306 | } | |
307 | fn est_bits(prob: u8, zeroes: u32, total: u32) -> u32 { | |
308 | (u32::from(PROB_BITS[prob as usize]) * zeroes + u32::from(PROB_BITS[256 - (prob as usize)]) * (total - zeroes) + 7) >> 3 | |
309 | } | |
310 | } | |
311 | ||
312 | #[derive(Clone,Copy,Default)] | |
313 | pub struct VP56MVModelStat { | |
314 | pub nz_prob: ProbCounter, | |
315 | pub sign_prob: ProbCounter, | |
316 | pub raw_probs: [ProbCounter; 8], | |
317 | pub tree_probs: [ProbCounter; 7], | |
318 | } | |
319 | ||
320 | #[derive(Clone,Copy,Default)] | |
321 | pub struct VP56CoeffModelStat { | |
322 | pub dc_token_probs: [[[ProbCounter; 5]; 6]; 6], | |
323 | pub dc_value_probs: [ProbCounter; 11], | |
324 | pub ac_val_probs: [[[ProbCounter; 11]; 6]; 3], | |
325 | } | |
326 | ||
327 | #[derive(Default)] | |
328 | pub struct VP6ModelsStat { | |
329 | pub zero_run_probs: [[ProbCounter; 14]; 2], | |
330 | } | |
331 | ||
332 | pub struct VP56ModelsStat { | |
333 | pub mv_models: [VP56MVModelStat; 2], | |
334 | pub mbtype_models: [[[usize; 10]; 10]; 3], | |
335 | pub coeff_models: [VP56CoeffModelStat; 2], | |
336 | pub vp6models: VP6ModelsStat, | |
337 | } | |
338 | ||
339 | impl VP56ModelsStat { | |
340 | pub fn new() -> Self { | |
341 | Self { | |
342 | mv_models: [VP56MVModelStat::default(); 2], | |
343 | mbtype_models: [[[0; 10]; 10]; 3], | |
344 | coeff_models: [VP56CoeffModelStat::default(); 2], | |
345 | vp6models: VP6ModelsStat::default(), | |
346 | } | |
347 | } | |
348 | pub fn reset(&mut self) { | |
349 | self.mv_models = [VP56MVModelStat::default(); 2]; | |
350 | self.mbtype_models = [[[0; 10]; 10]; 3]; | |
351 | self.coeff_models = [VP56CoeffModelStat::default(); 2]; | |
352 | self.vp6models = VP6ModelsStat::default(); | |
353 | } | |
354 | pub fn generate(&self, dst: &mut VP56Models, is_intra: bool) { | |
355 | if !is_intra { | |
356 | for (dmv, smv) in dst.mv_models.iter_mut().zip(self.mv_models.iter()) { | |
357 | dmv.nz_prob = smv.nz_prob.to_prob_worthy(dmv.nz_prob); | |
358 | dmv.sign_prob = smv.sign_prob.to_prob_worthy(dmv.sign_prob); | |
359 | for (dp, sp) in dmv.raw_probs.iter_mut().zip(smv.raw_probs.iter()) { | |
360 | *dp = sp.to_prob_worthy(*dp); | |
361 | } | |
362 | for (dp, sp) in dmv.tree_probs.iter_mut().zip(smv.tree_probs.iter()) { | |
363 | *dp = sp.to_prob_worthy(*dp); | |
364 | } | |
365 | } | |
366 | for (xmit, mdl) in dst.prob_xmitted.iter_mut().zip(self.mbtype_models.iter()) { | |
367 | Self::generate_prob_xmitted(xmit, mdl); | |
368 | } | |
369 | } | |
370 | for (dmv, smv) in dst.coeff_models.iter_mut().zip(self.coeff_models.iter()) { | |
371 | for (dp, sp) in dmv.dc_value_probs.iter_mut().zip(smv.dc_value_probs.iter()) { | |
372 | *dp = sp.to_prob_worthy(*dp); | |
373 | } | |
374 | for (dp, sp) in dmv.ac_val_probs.iter_mut().zip(smv.ac_val_probs.iter()) { | |
375 | for (dp, sp) in dp.iter_mut().zip(sp.iter()) { | |
376 | for (dp, sp) in dp.iter_mut().zip(sp.iter()) { | |
377 | *dp = sp.to_prob_worthy(*dp); | |
378 | } | |
379 | } | |
380 | } | |
381 | } | |
382 | for (dp, sp) in dst.vp6models.zero_run_probs.iter_mut().zip(self.vp6models.zero_run_probs.iter()) { | |
383 | for (dp, sp) in dp.iter_mut().zip(sp.iter()) { | |
384 | *dp = sp.to_prob_worthy(*dp); | |
385 | } | |
386 | } | |
387 | } | |
388 | /* | |
389 | VPMBType::InterNoMV => 0, | |
390 | VPMBType::Intra => 1, | |
391 | VPMBType::InterMV => 2, | |
392 | VPMBType::InterNearest => 3, | |
393 | VPMBType::InterNear => 4, | |
394 | VPMBType::GoldenNoMV => 5, | |
395 | VPMBType::GoldenMV => 6, | |
396 | VPMBType::InterFourMV => 7, | |
397 | VPMBType::GoldenNearest => 8, | |
398 | VPMBType::GoldenNear => 9, | |
399 | */ | |
400 | fn generate_prob_xmitted(probs: &mut [u8; 20], mbtype: &[[usize; 10]; 10]) { | |
401 | let mut sums = [0; 20]; | |
402 | let mut total = 0; | |
403 | for (last, row) in mbtype.iter().enumerate() { | |
404 | for (cur, &count) in row.iter().enumerate() { | |
405 | if last == cur { | |
406 | sums[cur * 2 + 1] = count; | |
407 | } else { | |
408 | sums[cur * 2] += count; | |
409 | } | |
410 | total += count; | |
411 | } | |
412 | } | |
413 | if total != 0 { | |
414 | let mut sum = 0; | |
415 | for (dprob, &sprob) in probs.iter_mut().zip(sums.iter()) { | |
416 | if sprob != 0 { | |
417 | *dprob = ((sprob * 256 + total - 1) / total).min(255) as u8; | |
418 | sum += u16::from(*dprob); | |
419 | } else { | |
420 | *dprob = 0; | |
421 | } | |
422 | } | |
423 | while sum > 256 { | |
424 | for prob in probs.iter_mut() { | |
425 | if *prob > 1 { | |
426 | *prob -= 1; | |
427 | sum -= 1; | |
428 | if sum == 256 { | |
429 | break; | |
430 | } | |
431 | } | |
432 | } | |
433 | } | |
434 | } else { | |
435 | *probs = [0; 20]; | |
436 | } | |
437 | } | |
438 | } |