]> git.nihav.org Git - nihav.git/blame - nihav-duck/src/codecs/vp56.rs
make audio decoder tests write .wav files only by request
[nihav.git] / nihav-duck / src / codecs / vp56.rs
CommitLineData
3584b223 1use nihav_core::codecs::*;
1fdbd53e 2use nihav_core::data::GenericCache;
3584b223
KS
3use nihav_core::io::bitreader::*;
4use super::vpcommon::*;
5
6pub const TOKEN_LARGE: u8 = 5;
7pub const TOKEN_EOB: u8 = 42;
8
9#[derive(Clone,Copy,Debug,Default)]
10#[allow(dead_code)]
11pub struct VP56Header {
12 pub is_intra: bool,
13 pub is_golden: bool,
14 pub quant: u8,
15 pub multistream: bool,
16 pub use_huffman: bool,
17 pub version: u8,
18 pub profile: u8,
19 pub interlaced: bool,
20 pub offset: u16,
21 pub mb_w: u8,
22 pub mb_h: u8,
23 pub disp_w: u8,
24 pub disp_h: u8,
25 pub scale: u8,
26}
27
28#[derive(Clone,Copy,Default)]
29pub struct VP56MVModel {
30 pub nz_prob: u8,
31 pub sign_prob: u8,
32 pub raw_probs: [u8; 8],
33 pub tree_probs: [u8; 7],
34}
35
36#[derive(Clone,Copy,Default)]
37pub struct VP56MBTypeModel {
38 pub probs: [u8; 10],
39}
40
41#[derive(Clone,Copy,Default)]
42pub struct VP56CoeffModel {
43 pub dc_token_probs: [[[u8; 5]; 6]; 6],
44 pub dc_value_probs: [u8; 11],
45 pub ac_ctype_probs: [[[[u8; 5]; 5]; 6]; 3],
46 pub ac_type_probs: [[[[u8; 5]; 6]; 3]; 3],
47 pub ac_val_probs: [[[u8; 11]; 6]; 3],
48}
49
50pub struct VP6Models {
51 pub scan_order: [usize; 64],
52 pub scan: [usize; 64],
53 pub zigzag: [usize; 64],
54 pub zero_run_probs: [[u8; 14]; 2],
55}
56
57const MAX_HUFF_ELEMS: usize = 12;
58#[derive(Clone,Copy,Default)]
59pub struct VP6Huff {
60 pub codes: [u16; MAX_HUFF_ELEMS],
61 pub bits: [u8; MAX_HUFF_ELEMS],
62}
63
64#[derive(Clone,Copy,Default)]
65struct Node {
66 weight: u16,
67 sym: i8,
68 ch0: usize,
69 ch1: usize,
70}
71
72fn prob2weight(a: u8, b: u8) -> u8 {
73 let w = (((a as u16) * (b as u16)) >> 8) as u8;
74 if w == 0 {
75 1
76 } else {
77 w
78 }
79}
80
81impl VP6Huff {
82 fn build_codes(&mut self, probs: &[u8; 11]) {
83 let mut weights = [0u8; 12];
84
85 weights[11] = prob2weight( probs[0], probs[ 1]);
86 weights[ 0] = prob2weight( probs[0], !probs[ 1]);
87 weights[ 1] = prob2weight(!probs[0], probs[ 2]);
88 let lvroot = prob2weight(!probs[0], !probs[ 2]);
89 let tworoot = prob2weight( lvroot, probs[ 3]);
90 let hlroot = prob2weight( lvroot, !probs[ 3]);
91 weights[ 2] = prob2weight( tworoot, probs[ 4]);
92 let root34 = prob2weight( tworoot, !probs[ 4]);
93 weights[ 3] = prob2weight( root34, probs[ 5]);
94 weights[ 4] = prob2weight( root34, !probs[ 5]);
95 let c1root = prob2weight( hlroot, probs[ 6]);
96 let c34root = prob2weight( hlroot, !probs[ 6]);
97 weights[ 5] = prob2weight( c1root, probs[ 7]);
98 weights[ 6] = prob2weight( c1root, !probs[ 7]);
99 let c3root = prob2weight( c34root, probs[ 8]);
100 let c4root = prob2weight( c34root, !probs[ 8]);
101 weights[ 7] = prob2weight( c3root, probs[ 9]);
102 weights[ 8] = prob2weight( c3root, !probs[ 9]);
103 weights[ 9] = prob2weight( c4root, probs[10]);
104 weights[10] = prob2weight( c4root, !probs[10]);
105
106 self.build(&weights);
107 }
108 fn build_codes_zero_run(&mut self, probs: &[u8; 14]) {
109 let mut weights = [0u8; 9];
110
111 let root = prob2weight( probs[0], probs[1]);
112 weights[0] = prob2weight( root, probs[2]);
113 weights[1] = prob2weight( root, !probs[2]);
114
115 let root = prob2weight( probs[0], !probs[1]);
116 weights[2] = prob2weight( root, probs[3]);
117 weights[3] = prob2weight( root, !probs[3]);
118
119 let root = prob2weight(!probs[0], probs[4]);
120 weights[8] = prob2weight(!probs[0], !probs[4]);
121 let root1 = prob2weight( root, probs[5]);
122 let root2 = prob2weight( root, !probs[5]);
123 weights[4] = prob2weight( root1, probs[6]);
124 weights[5] = prob2weight( root1, !probs[6]);
125 weights[6] = prob2weight( root2, probs[7]);
126 weights[7] = prob2weight( root2, !probs[7]);
127
128 self.build(&weights);
129 }
130 fn build(&mut self, weights: &[u8]) {
131 let mut nodes = [Node::default(); MAX_HUFF_ELEMS * 2];
132 let mut nlen = 0;
133
134 for w in weights.iter().rev() {
135 let weight = *w as u16;
136 let mut pos = nlen;
137 for i in 0..nlen {
138 if nodes[i].weight > weight {
139 pos = i;
140 break;
141 }
142 }
143 for j in (pos..nlen).rev() {
144 nodes[j + 1] = nodes[j];
145 }
146 nodes[pos].weight = weight;
147 nodes[pos].sym = (weights.len() - nlen - 1) as i8;
148 nlen += 1;
149 }
150
151 let mut low = 0;
152 for _ in 0..nlen-1 {
153 let nnode = Node {
154 weight: nodes[low + 0].weight + nodes[low + 1].weight,
155 sym: -1,
156 ch0: low + 0,
157 ch1: low + 1,
158 };
159 low += 2;
160 let mut pos = low;
161 while (pos < nlen) && (nodes[pos].weight < nnode.weight) {
162 pos += 1;
163 }
164 for j in (pos..nlen).rev() {
165 nodes[j + 1] = nodes[j];
166 }
167 nodes[pos] = nnode;
168 nlen += 1;
169 }
170 self.get_codes(&nodes, nlen - 1, 0, 0);
171 for i in nlen..self.codes.len() {
172 self.codes[i] = self.codes[0];
173 self.bits[i] = self.bits[0];
174 }
175 }
176 fn get_codes(&mut self, nodes: &[Node], pos: usize, code: u16, len: u8) {
177 if nodes[pos].sym >= 0 {
178 self.codes[nodes[pos].sym as usize] = code;
179 self.bits [nodes[pos].sym as usize] = len;
180 } else {
181 self.get_codes(nodes, nodes[pos].ch0, (code << 1) | 0, len + 1);
182 self.get_codes(nodes, nodes[pos].ch1, (code << 1) | 1, len + 1);
183 }
184 }
185}
186
187pub trait ReadHuff {
188 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8>;
189}
190
191impl<'a> ReadHuff for BitReader<'a> {
192 fn read_huff(&mut self, huff: &VP6Huff) -> DecoderResult<u8> {
193 let peekval = self.peek(16);
194 for (i, (code, bit)) in huff.codes.iter().zip(huff.bits.iter()).enumerate() {
195 if (peekval >> (16 - *bit)) == (*code as u32) {
196 self.skip(*bit as u32)?;
197 return Ok(i as u8);
198 }
199 }
200 Err(DecoderError::InvalidData)
201 }
202}
203
204#[derive(Clone,Copy,Default)]
205pub struct VP6HuffModels {
206 pub dc_token_tree: [VP6Huff; 2],
207 pub ac_token_tree: [[[VP6Huff; 6]; 3]; 2],
208 pub zero_run_tree: [VP6Huff; 2],
209}
210
211impl VP6Models {
212 fn new() -> Self {
213 Self {
214 scan_order: [0; 64],
215 scan: [0; 64],
216 zigzag: [0; 64],
217 zero_run_probs: [[0; 14]; 2],
218 }
219 }
220}
221
222pub struct VP56Models {
223 pub mv_models: [VP56MVModel; 2],
224 pub mbtype_models: [[VP56MBTypeModel; 10]; 3],
225 pub coeff_models: [VP56CoeffModel; 2],
226 pub prob_xmitted: [[u8; 20]; 3],
227 pub vp6models: VP6Models,
228 pub vp6huff: VP6HuffModels,
229}
230
231impl VP56Models {
232 fn new() -> Self {
233 Self {
234 mv_models: [VP56MVModel::default(); 2],
235 mbtype_models: [[VP56MBTypeModel::default(); 10]; 3],
236 coeff_models: [VP56CoeffModel::default(); 2],
237 prob_xmitted: [[0; 20]; 3],
238 vp6models: VP6Models::new(),
239 vp6huff: VP6HuffModels::default(),
240 }
241 }
242}
243
244pub trait VP56Parser {
245 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header>;
246 fn reset_models(&self, models: &mut VP56Models);
247 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16;
248 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()>;
249 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()>;
250 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()>;
251 fn decode_block_huff(&self, br: &mut BitReader, coeffs: &mut [i16; 64], vp6model: &VP6Models, model: &VP6HuffModels, fstate: &mut FrameState) -> DecoderResult<()>;
252 fn mc_block(&self, dst: &mut NASimpleVideoFrame<u8>, mc_buf: NAVideoBufferRef<u8>, src: NAVideoBufferRef<u8>, plane: usize, x: usize, y: usize, mv: MV, loop_thr: i16);
253}
254
255enum CoeffReader<'a> {
256 None,
257 Bool(BoolCoder<'a>),
258 Huff(BitReader<'a>),
259}
260
261#[derive(Clone,Copy,Default)]
262struct MBInfo {
263 mb_type: VPMBType,
264 mv: MV,
265}
266
267pub struct FrameState {
268 pub mb_x: usize,
269 pub mb_y: usize,
270 pub plane: usize,
271 pub coeff_cat: [[u8; 64]; 4],
272 pub last_idx: [usize; 4],
273 pub top_ctx: u8,
274 pub ctx_idx: usize,
275 pub dc_quant: i16,
276 pub ac_quant: i16,
277 pub dc_zero_run: [usize; 2],
278 pub ac_zero_run: [usize; 2],
279}
280
281impl FrameState {
282 fn new() -> Self {
283 Self {
284 mb_x: 0,
285 mb_y: 0,
286 plane: 0,
287 coeff_cat: [[0; 64]; 4],
288 last_idx: [0; 4],
289 top_ctx: 0,
290 ctx_idx: 0,
291 dc_quant: 0,
292 ac_quant: 0,
293 dc_zero_run: [0; 2],
294 ac_zero_run: [0; 2],
295 }
296 }
297}
298
3584b223
KS
299pub struct VP56Decoder {
300 version: u8,
301 has_alpha: bool,
302 flip: bool,
303 shuf: VPShuffler,
304 width: usize,
305 height: usize,
306 mb_w: usize,
307 mb_h: usize,
308 models: VP56Models,
309 coeffs: [[i16; 64]; 6],
310 last_mbt: VPMBType,
311
312 loop_thr: i16,
313 ilace_prob: u8,
314 ilace_mb: bool,
315
316 mb_info: Vec<MBInfo>,
317 fstate: FrameState,
318 dc_y: GenericCache<i16>,
319 dc_u: GenericCache<i16>,
320 dc_v: GenericCache<i16>,
321 dc_a: GenericCache<i16>,
322 last_dc: [[i16; 4]; 3],
323 top_ctx: [Vec<u8>; 4],
324
325 mc_buf: NAVideoBufferRef<u8>,
326}
327
328fn rescale_mb_mode_prob(prob: u32, total: u32) -> u8 {
329 (255 * prob / (1 + total)) as u8
330}
331
332fn map_mb_type(mbtype: VPMBType) -> usize {
333 match mbtype {
334 VPMBType::InterNoMV => 0,
335 VPMBType::Intra => 1,
336 VPMBType::InterMV => 2,
337 VPMBType::InterNearest => 3,
338 VPMBType::InterNear => 4,
339 VPMBType::GoldenNoMV => 5,
340 VPMBType::GoldenMV => 6,
341 VPMBType::InterFourMV => 7,
342 VPMBType::GoldenNearest => 8,
343 VPMBType::GoldenNear => 9,
344 }
345}
346
3584b223 347pub fn expand_token_bc(bc: &mut BoolCoder, val_probs: &[u8; 11], token: u8, version: u8) -> i16 {
3584b223
KS
348 let mut sign = false;
349 let level;
350 if token < TOKEN_LARGE {
351 if token != 0 {
352 sign = bc.read_bool();
353 }
354 level = token as i16;
355 } else {
356 let cat: usize = vp_tree!(bc, val_probs[6],
357 vp_tree!(bc, val_probs[7], 0, 1),
358 vp_tree!(bc, val_probs[8],
359 vp_tree!(bc, val_probs[9], 2, 3),
360 vp_tree!(bc, val_probs[10], 4, 5)));
361 if version == 5 {
362 sign = bc.read_bool();
363 }
364 let mut add = 0i16;
3f67638d 365 let add_probs = &VP56_COEF_ADD_PROBS[cat];
3584b223
KS
366 for prob in add_probs.iter() {
367 if *prob == 128 { break; }
368 add = (add << 1) | (bc.read_prob(*prob) as i16);
369 }
370 if version != 5 {
371 sign = bc.read_bool();
372 }
373 level = VP56_COEF_BASE[cat] + add;
374 }
375 if !sign {
376 level
377 } else {
378 -level
379 }
380}
381
382impl VP56Decoder {
383 pub fn new(version: u8, has_alpha: bool, flip: bool) -> Self {
384 let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, YUV420_FORMAT), 4).unwrap();
385 let mc_buf = vt.get_vbuf().unwrap();
386 Self {
387 version, has_alpha, flip,
388 shuf: VPShuffler::new(),
389 width: 0,
390 height: 0,
391 mb_w: 0,
392 mb_h: 0,
393 models: VP56Models::new(),
394 coeffs: [[0; 64]; 6],
395 last_mbt: VPMBType::InterNoMV,
396
397 loop_thr: 0,
398 ilace_prob: 0,
399 ilace_mb: false,
400
401 mb_info: Vec::new(),
402 fstate: FrameState::new(),
403 dc_y: GenericCache::new(0, 0, 0),
404 dc_u: GenericCache::new(0, 0, 0),
405 dc_v: GenericCache::new(0, 0, 0),
406 dc_a: GenericCache::new(0, 0, 0),
407 last_dc: [[0; 4]; 3],
408 top_ctx: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
409
410 mc_buf,
411 }
412 }
413 fn set_dimensions(&mut self, width: usize, height: usize) {
414 self.width = width;
415 self.height = height;
416 self.mb_w = (self.width + 15) >> 4;
417 self.mb_h = (self.height + 15) >> 4;
418 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
419 self.dc_y = GenericCache::new(2, 1 + self.mb_w * 2, 0);
420 self.dc_u = GenericCache::new(1, 1 + self.mb_w, 0);
421 self.dc_v = GenericCache::new(1, 1 + self.mb_w, 0);
422 self.dc_a = GenericCache::new(2, 1 + self.mb_w * 2, 0);
423 self.top_ctx = [vec![0; self.mb_w * 2], vec![0; self.mb_w], vec![0; self.mb_w], vec![0; self.mb_w * 2]];
424 }
425 pub fn init(&mut self, supp: &mut NADecoderSupport, vinfo: NAVideoInfo) -> DecoderResult<()> {
426 supp.pool_u8.set_dec_bufs(3);
427 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, vinfo.get_format()), 4)?;
428 self.set_dimensions(vinfo.get_width(), vinfo.get_height());
429 Ok(())
430 }
f9be4e75
KS
431 pub fn flush(&mut self) {
432 self.shuf.clear();
433 }
3584b223
KS
434 pub fn decode_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], br: &mut dyn VP56Parser) -> DecoderResult<(NABufferType, FrameType)> {
435 let aoffset;
436 let mut bc;
437 if self.has_alpha {
438 validate!(src.len() >= 7);
439 aoffset = ((src[0] as usize) << 16) | ((src[1] as usize) << 8) | (src[2] as usize);
440 validate!((aoffset > 0) && (aoffset < src.len() - 3));
441 bc = BoolCoder::new(&src[3..])?;
442 } else {
443 validate!(src.len() >= 4);
444 aoffset = src.len();
445 bc = BoolCoder::new(src)?;
446 }
447 let hdr = br.parse_header(&mut bc)?;
448 validate!((hdr.offset as usize) < aoffset); //XXX: take alpha 3 byte offset into account?
449
450 if hdr.mb_w != 0 {
451 self.set_dimensions((hdr.mb_w as usize) * 16, (hdr.mb_h as usize) * 16);
452 }
453 let vinfo = NAVideoInfo::new(self.width, self.height, self.flip, YUV420_FORMAT);
454 let ret = supp.pool_u8.get_free();
455 if ret.is_none() {
456 return Err(DecoderError::AllocError);
457 }
458 let mut buf = ret.unwrap();
459 if buf.get_info() != vinfo {
460 self.shuf.clear();
461 supp.pool_u8.reset();
462 supp.pool_u8.prealloc_video(vinfo, 4)?;
463 let ret = supp.pool_u8.get_free();
464 if ret.is_none() {
465 return Err(DecoderError::AllocError);
466 }
467 buf = ret.unwrap();
468 }
469 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
470
471 if hdr.is_intra {
472 self.shuf.clear();
6e24ec0b
KS
473 } else {
474 if !self.shuf.has_refs() {
475 return Err(DecoderError::MissingReference);
476 }
3584b223
KS
477 }
478
479 let mut cr;
480 if hdr.multistream {
481 let off = (if self.has_alpha { 3 } else { 0 }) + (hdr.offset as usize);
482 if !hdr.use_huffman {
483 let bc2 = BoolCoder::new(&src[off..])?;
484 cr = CoeffReader::Bool(bc2);
485 } else {
486 let br = BitReader::new(&src[off..], aoffset - off, BitReaderMode::BE);
487 cr = CoeffReader::Huff(br);
488 }
489 } else {
490 cr = CoeffReader::None;
491 }
492
493 if hdr.is_intra {
494 br.reset_models(&mut self.models);
495 self.reset_mbtype_models();
496 } else {
497 self.decode_mode_prob_models(&mut bc)?;
498 br.decode_mv_models(&mut bc, &mut self.models.mv_models)?;
499 }
500 br.decode_coeff_models(&mut bc, &mut self.models, hdr.is_intra)?;
501 if hdr.use_huffman {
502 for i in 0..2 {
503 self.models.vp6huff.dc_token_tree[i].build_codes(&self.models.coeff_models[i].dc_value_probs);
504 }
505 for i in 0..2 {
506 for mode in 0..3 {
507 for band in 0..6 {
508 self.models.vp6huff.ac_token_tree[i][mode][band].build_codes(&self.models.coeff_models[i].ac_val_probs[mode][band]);
509 }
510 }
511 }
512 for i in 0..2 {
513 self.models.vp6huff.zero_run_tree[i].build_codes_zero_run(&self.models.vp6models.zero_run_probs[i]);
514 }
515 }
516
517 if hdr.interlaced {
518 self.ilace_prob = bc.read_bits(8) as u8;
519 }
520
521 self.fstate = FrameState::new();
522 self.fstate.dc_quant = VP56_DC_QUANTS[hdr.quant as usize] * 4;
523 self.fstate.ac_quant = VP56_AC_QUANTS[hdr.quant as usize] * 4;
524 self.loop_thr = VP56_FILTER_LIMITS[hdr.quant as usize] as i16;
525
526 self.last_mbt = VPMBType::InterNoMV;
527 self.dc_y.reset();
528 self.dc_u.reset();
529 self.dc_v.reset();
530 self.dc_a.reset();
531 for vec in self.top_ctx.iter_mut() {
532 for el in vec.iter_mut() {
533 *el = 0;
534 }
535 }
536 self.last_dc = [[0; 4]; 3];
537 self.last_dc[0][1] = 0x80;
538 self.last_dc[0][2] = 0x80;
539
540 self.ilace_mb = false;
541 for mb_y in 0..self.mb_h {
542 self.fstate.mb_y = mb_y;
543 self.fstate.coeff_cat = [[0; 64]; 4];
544 self.fstate.last_idx = [24; 4];
545 for mb_x in 0..self.mb_w {
546 self.fstate.mb_x = mb_x;
547 self.decode_mb(&mut dframe, &mut bc, &mut cr, br, &hdr, false)?;
548 }
549 self.dc_y.update_row();
550 self.dc_u.update_row();
551 self.dc_v.update_row();
552 self.dc_a.update_row();
553 }
554
555 if self.has_alpha {
556 let asrc = &src[aoffset + 3..];
557 let mut bc = BoolCoder::new(asrc)?;
558 let ahdr = br.parse_header(&mut bc)?;
559 validate!(ahdr.mb_w == hdr.mb_w && ahdr.mb_h == hdr.mb_h);
560 }
561
562 if hdr.is_golden {
563 self.shuf.add_golden_frame(buf.clone());
564 }
565 self.shuf.add_frame(buf.clone());
566
567 Ok((NABufferType::Video(buf), if hdr.is_intra { FrameType::I } else { FrameType::P }))
568 }
569 fn reset_mbtype_models(&mut self) {
570 const DEFAULT_XMITTED_PROBS: [[u8; 20]; 3] = [
571 [ 42, 69, 2, 1, 7, 1, 42, 44, 22, 6, 3, 1, 2, 0, 5, 1, 1, 0, 0, 0 ],
572 [ 8, 229, 1, 1, 8, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 0, 0 ],
573 [ 35, 122, 1, 1, 6, 1, 34, 46, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1, 0, 0 ]
574 ];
575 self.models.prob_xmitted.copy_from_slice(&DEFAULT_XMITTED_PROBS);
576 }
577 fn decode_mode_prob_models(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
578 for ctx in 0..3 {
579 if bc.read_prob(174) {
580 let idx = bc.read_bits(4) as usize;
581 for i in 0..20 {
582 self.models.prob_xmitted[ctx][i ^ 1] = VP56_MODE_VQ[ctx][idx][i];
583 }
584 }
585 if bc.read_prob(254) {
586 for set in 0..20 {
587 if bc.read_prob(205) {
588 let sign = bc.read_bool();
589 let diff = vp_tree!(bc, 171,
590 vp_tree!(bc, 83, 2, 1),
591 vp_tree!(bc, 199,
592 vp_tree!(bc, 140,
593 vp_tree!(bc, 125,
594 vp_tree!(bc, 104, 6, 5),
595 4
596 ),
597 3
598 ),
599 bc.read_bits(7)
600 )) * 4;
601 validate!(diff < 256);
602 let diff = diff as u8;
603 if !sign {
604 validate!(self.models.prob_xmitted[ctx][set ^ 1] <= 255 - diff);
605 self.models.prob_xmitted[ctx][set ^ 1] += diff;
606 } else {
607 validate!(self.models.prob_xmitted[ctx][set ^ 1] >= diff);
608 self.models.prob_xmitted[ctx][set ^ 1] -= diff;
609 }
610 }
611 }
612 }
613 }
614 for ctx in 0..3 {
615 let prob_xmitted = &self.models.prob_xmitted[ctx];
616 for mode in 0..10 {
617 let mdl = &mut self.models.mbtype_models[ctx][mode];
618 let mut cnt = [0u32; 10];
619 let mut total = 0;
620 for i in 0..10 {
621 if i == mode { continue; }
622 cnt[i] = 100 * (prob_xmitted[i * 2] as u32);
623 total += cnt[i];
624 }
625 let sum = (prob_xmitted[mode * 2] as u32) + (prob_xmitted[mode * 2 + 1] as u32);
626 mdl.probs[9] = 255 - rescale_mb_mode_prob(prob_xmitted[mode * 2 + 1] as u32, sum);
627
628 let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
629 let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
630 let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
631 let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
632 let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
633 mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
634 mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
635 mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
636 mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
637 mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
638 mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
639 mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
640 mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
641 mdl.probs[8] = 1 + rescale_mb_mode_prob(cnt[8], gold_mv1_weight);
642 }
643 }
644 Ok(())
645 }
646 fn find_mv_pred(&self, ref_id: u8) -> (usize, MV, MV, MV) {
647 const CAND_POS: [(i8, i8); 12] = [
648 (-1, 0), ( 0, -1),
649 (-1, -1), (-1, 1),
650 (-2, 0), ( 0, -2),
651 (-1, -2), (-2, -1),
652 (-2, 1), (-1, 2),
653 (-2, -2), (-2, 2)
654 ];
655
656 let mut nearest_mv = ZERO_MV;
657 let mut near_mv = ZERO_MV;
658 let mut pred_mv = ZERO_MV;
659 let mut num_mv: usize = 0;
660
661 for (i, (yoff, xoff)) in CAND_POS.iter().enumerate() {
662 let cx = (self.fstate.mb_x as isize) + (*xoff as isize);
663 let cy = (self.fstate.mb_y as isize) + (*yoff as isize);
664 if (cx < 0) || (cy < 0) {
665 continue;
666 }
667 let cx = cx as usize;
668 let cy = cy as usize;
669 if (cx >= self.mb_w) || (cy >= self.mb_h) {
670 continue;
671 }
672 let mb_pos = cx + cy * self.mb_w;
673 let mv = self.mb_info[mb_pos].mv;
674 if (self.mb_info[mb_pos].mb_type.get_ref_id() != ref_id) || (mv == ZERO_MV) {
675 continue;
676 }
677 if num_mv == 0 {
678 nearest_mv = mv;
679 num_mv += 1;
680 if (self.version > 5) && (i < 2) {
681 pred_mv = mv;
682 }
683 } else if mv != nearest_mv {
684 near_mv = mv;
685 num_mv += 1;
686 break;
687 }
688 }
689
690 (num_mv, nearest_mv, near_mv, pred_mv)
691 }
692 fn decode_mv(&self, bc: &mut BoolCoder, br: &mut dyn VP56Parser) -> MV {
693 let x = br.decode_mv(bc, &self.models.mv_models[0]);
694 let y = br.decode_mv(bc, &self.models.mv_models[1]);
695 MV{ x, y }
696 }
697 fn decode_mb_type(&mut self, bc: &mut BoolCoder, ctx: usize) -> DecoderResult<VPMBType> {
698 let probs = &self.models.mbtype_models[ctx][map_mb_type(self.last_mbt)].probs;
699 if !bc.read_prob(probs[9]) {
700 self.last_mbt = vp_tree!(
701 bc, probs[0],
702 vp_tree!(bc, probs[1],
703 vp_tree!(bc, probs[3], VPMBType::InterNoMV, VPMBType::InterMV),
704 vp_tree!(bc, probs[4], VPMBType::InterNearest, VPMBType::InterNear)
705 ),
706 vp_tree!(bc, probs[2],
707 vp_tree!(bc, probs[5], VPMBType::Intra, VPMBType::InterFourMV),
708 vp_tree!(bc, probs[6],
709 vp_tree!(bc, probs[7], VPMBType::GoldenNoMV, VPMBType::GoldenMV),
710 vp_tree!(bc, probs[8], VPMBType::InterNearest, VPMBType::InterNear)
711 )
712 )
713 );
714 }
715 Ok(self.last_mbt)
716 }
717 fn decode_mb(&mut self, frm: &mut NASimpleVideoFrame<u8>, bc: &mut BoolCoder, cr: &mut CoeffReader, br: &mut dyn VP56Parser, hdr: &VP56Header, alpha: bool) -> DecoderResult<()> {
718 const FOURMV_SUB_TYPE: [VPMBType; 4] = [ VPMBType::InterNoMV, VPMBType::InterMV, VPMBType::InterNearest, VPMBType::InterNear ];
719
720 let mb_x = self.fstate.mb_x;
721 let mb_y = self.fstate.mb_y;
722 self.coeffs = [[0; 64]; 6];
723 let mb_pos = mb_x + mb_y * self.mb_w;
724 let mut four_mv = [ZERO_MV; 4];
725 let mut four_mbt = [VPMBType::Intra; 4];
726
727 if hdr.interlaced {
728 let iprob = self.ilace_prob;
729 let prob = if mb_x == 0 {
730 iprob
731 } else if !self.ilace_mb {
732 iprob + (((256 - (iprob as u16)) >> 1) as u8)
733 } else {
734 iprob - (iprob >> 1)
735 };
736 self.ilace_mb = bc.read_prob(prob);
737 }
738
739 let (num_mv, nearest_mv, near_mv, pred_mv) = if hdr.is_intra {
740 (0, ZERO_MV, ZERO_MV, ZERO_MV)
741 } else { self.find_mv_pred(VP_REF_INTER) };
742 let mb_type = if hdr.is_intra {
743 VPMBType::Intra
744 } else {
745 self.decode_mb_type(bc, (num_mv + 1) % 3)?
746 };
747 self.mb_info[mb_pos].mb_type = mb_type;
748 if mb_type.get_ref_id() != VP_REF_GOLDEN {
749 match mb_type {
750 VPMBType::Intra |
751 VPMBType::InterNoMV => {
752 self.mb_info[mb_pos].mv = ZERO_MV;
753 },
754 VPMBType::InterMV => {
755 let diff_mv = self.decode_mv(bc, br);
756 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
757 },
758 VPMBType::InterNearest => {
759 self.mb_info[mb_pos].mv = nearest_mv;
760 },
761 VPMBType::InterNear => {
762 self.mb_info[mb_pos].mv = near_mv;
763 },
764 VPMBType::InterFourMV => {
765 for i in 0..4 {
766 four_mbt[i] = FOURMV_SUB_TYPE[bc.read_bits(2) as usize];
767 }
768 for i in 0..4 {
769 match four_mbt[i] {
770 VPMBType::InterNoMV => {},
771 VPMBType::InterMV => {
772 let diff_mv = self.decode_mv(bc, br);
773 four_mv[i] = pred_mv + diff_mv;
774 },
775 VPMBType::InterNearest => {
776 four_mv[i] = nearest_mv;
777 },
778 VPMBType::InterNear => {
779 four_mv[i] = near_mv;
780 },
781 _ => unreachable!(),
782 };
783 }
784 self.mb_info[mb_pos].mv = four_mv[3];
785 },
786 _ => unreachable!(),
787 };
788 } else {
789 let (_num_mv, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(VP_REF_GOLDEN);
790 match mb_type {
791 VPMBType::GoldenNoMV => {
792 self.mb_info[mb_pos].mv = ZERO_MV;
793 },
794 VPMBType::GoldenMV => {
795 let diff_mv = self.decode_mv(bc, br);
796 self.mb_info[mb_pos].mv = pred_mv + diff_mv;
797 },
798 VPMBType::GoldenNearest => {
799 self.mb_info[mb_pos].mv = nearest_mv;
800 },
801 VPMBType::GoldenNear => {
802 self.mb_info[mb_pos].mv = near_mv;
803 },
804 _ => unreachable!(),
805 };
806 }
807 if !mb_type.is_intra() && (mb_type != VPMBType::InterFourMV) {
808 self.do_mc(br, frm, mb_type, self.mb_info[mb_pos].mv, alpha);
809 } else if mb_type == VPMBType::InterFourMV {
810 self.do_fourmv(br, frm, &four_mv, alpha);
811 }
812
813 for blk_no in 0..4 {
814 self.fstate.plane = if !alpha { 0 } else { 3 };
815 self.fstate.ctx_idx = blk_no >> 1;
816 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)];
817 match cr {
818 CoeffReader::None => {
819 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
820 },
821 CoeffReader::Bool(ref mut bcc) => {
822 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[0], &self.models.vp6models, &mut self.fstate)?;
823 },
824 CoeffReader::Huff(ref mut brc) => {
825 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
826 },
827 };
828 self.top_ctx[self.fstate.plane][mb_x * 2 + (blk_no & 1)] = self.fstate.top_ctx;
829 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
830
831 let bx = mb_x * 2 + (blk_no & 1);
832 let by = mb_y * 2 + (blk_no >> 1);
833 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
834 if mb_type.is_intra() {
835 if !self.ilace_mb {
836 if has_ac {
837 vp_put_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
838 } else {
839 vp_put_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
840 }
841 } else {
842 vp_put_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
843 }
844 } else {
845 if !self.ilace_mb {
846 if has_ac {
847 vp_add_block(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
848 } else {
849 vp_add_block_dc(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
850 }
851 } else {
852 vp_add_block_ilace(&mut self.coeffs[blk_no], bx, by, self.fstate.plane, frm);
853 }
854 }
855 }
856 if !alpha {
857 for blk_no in 4..6 {
858 self.fstate.plane = blk_no - 3;
859 self.fstate.ctx_idx = blk_no - 2;
860 self.fstate.top_ctx = self.top_ctx[self.fstate.plane][mb_x];
861 match cr {
862 CoeffReader::None => {
863 br.decode_block(bc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
864 },
865 CoeffReader::Bool(ref mut bcc) => {
866 br.decode_block(bcc, &mut self.coeffs[blk_no], &self.models.coeff_models[1], &self.models.vp6models, &mut self.fstate)?;
867 },
868 CoeffReader::Huff(ref mut brc) => {
869 br.decode_block_huff(brc, &mut self.coeffs[blk_no], &self.models.vp6models, &self.models.vp6huff, &mut self.fstate)?;
870 },
871 };
872 self.top_ctx[self.fstate.plane][mb_x] = self.fstate.top_ctx;
873 self.predict_dc(mb_type, mb_pos, blk_no, alpha);
874
875 let has_ac = self.fstate.last_idx[self.fstate.ctx_idx] > 0;
876 if mb_type.is_intra() {
877 if has_ac {
878 vp_put_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
879 } else {
880 vp_put_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
881 }
882 } else {
883 if has_ac {
884 vp_add_block(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
885 } else {
886 vp_add_block_dc(&mut self.coeffs[blk_no], mb_x, mb_y, self.fstate.plane, frm);
887 }
888 }
889 }
890 }
891 Ok(())
892 }
893 fn do_mc(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mb_type: VPMBType, mv: MV, alpha: bool) {
894 let x = self.fstate.mb_x * 16;
895 let y = self.fstate.mb_y * 16;
896 let plane = if !alpha { 0 } else { 3 };
897 let src = if mb_type.get_ref_id() == VP_REF_INTER {
898 self.shuf.get_last().unwrap()
899 } else {
900 self.shuf.get_golden().unwrap()
901 };
902
903 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 0, mv, self.loop_thr);
904 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 0, mv, self.loop_thr);
905 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 0, y + 8, mv, self.loop_thr);
906 br.mc_block(frm, self.mc_buf.clone(), src.clone(), plane, x + 8, y + 8, mv, self.loop_thr);
907 if !alpha {
908 let x = self.fstate.mb_x * 8;
909 let y = self.fstate.mb_y * 8;
910 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
911 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
912 }
913 }
914 fn do_fourmv(&mut self, br: &dyn VP56Parser, frm: &mut NASimpleVideoFrame<u8>, mvs: &[MV; 4], alpha: bool) {
915 let x = self.fstate.mb_x * 16;
916 let y = self.fstate.mb_y * 16;
917 let plane = if !alpha { 0 } else { 3 };
918 let src = self.shuf.get_last().unwrap();
919 for blk_no in 0..4 {
920 br.mc_block(frm, self.mc_buf.clone(), src.clone(),
921 plane, x + (blk_no & 1) * 8, y + (blk_no & 2) * 4,
922 mvs[blk_no], self.loop_thr);
923 }
924 if !alpha {
925 let x = self.fstate.mb_x * 8;
926 let y = self.fstate.mb_y * 8;
927 let sum = mvs[0] + mvs[1] + mvs[2] + mvs[3];
928 let mv = MV { x: sum.x / 4, y: sum.y / 4 };
929 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 1, x, y, mv, self.loop_thr);
930 br.mc_block(frm, self.mc_buf.clone(), src.clone(), 2, x, y, mv, self.loop_thr);
931 }
932 }
933 fn predict_dc(&mut self, mb_type: VPMBType, mb_pos: usize, blk_no: usize, alpha: bool) {
934 let mb_x = self.fstate.mb_x;
935 let is_luma = blk_no < 4;
936 let (plane, dcs) = if alpha { (0, &mut self.dc_a) } else {
937 match blk_no {
938 4 => (1, &mut self.dc_u),
939 5 => (2, &mut self.dc_v),
940 _ => (0, &mut self.dc_y),
941 }
942 };
943 let dc_pos = if is_luma {
944 dcs.xpos + mb_x * 2 + (blk_no & 1) + (blk_no >> 1) * dcs.stride
945 } else {
946 dcs.xpos + mb_x
947 };
948 let ref_id = mb_type.get_ref_id();
949 let has_left_blk = is_luma && ((blk_no & 1) != 0);
950 let has_top_blk = is_luma && ((blk_no & 2) != 0);
951 let mut dc_pred = 0;
952 let mut count = 0;
953 if has_left_blk || ((mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id)) {
954 dc_pred += dcs.data[dc_pos - 1];
955 count += 1;
956 }
957 if has_top_blk || ((mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id)) {
958 dc_pred += dcs.data[dc_pos - dcs.stride];
959 count += 1;
960 }
961 if self.version == 5 {
962 if (count < 2) && has_left_blk {
963 dc_pred += dc_pred;
964 count += 1;
965 }
966 if (count < 2) && !has_left_blk && has_top_blk && (mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id) {
967 dc_pred += dc_pred;
968 count += 1;
969 }
970 if (count < 2) && mb_pos == 0 && !is_luma {
971 count += 1;
972 }
973 if (count < 2) && !has_left_blk && !has_top_blk && is_luma && (mb_x > 0) && (self.mb_info[mb_pos - 1].mb_type.get_ref_id() == ref_id) {
974 dc_pred += dcs.data[dc_pos + dcs.stride - 1];
975 count += 1;
976 }
977 if (count < 2) && blk_no == 2 {
978 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
979 count += 1;
980 }
981 if (count < 2) && !has_left_blk && (mb_pos >= self.mb_w) && (self.mb_info[mb_pos - self.mb_w].mb_type.get_ref_id() == ref_id) {
982 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
983 count += 1;
984 }
985 if (count < 2) && has_left_blk && (mb_pos > self.mb_w) && (mb_x < self.mb_w - 1) && (self.mb_info[mb_pos - self.mb_w + 1].mb_type.get_ref_id() == ref_id) {
986 dc_pred += dcs.data[dc_pos - dcs.stride + 1];
987 count += 1;
988 }
989 }
990 if count == 0 {
991 dc_pred = self.last_dc[ref_id as usize][plane];
992 } else if count == 2 {
993 dc_pred /= 2;
994 }
995 self.coeffs[blk_no][0] += dc_pred;
996 self.last_dc[ref_id as usize][plane] = self.coeffs[blk_no][0];
997 dcs.data[dc_pos] = self.coeffs[blk_no][0];
998 self.coeffs[blk_no][0] = self.coeffs[blk_no][0].wrapping_mul(self.fstate.dc_quant);
999 }
1000}
1001
1002const VP56_DC_QUANTS: [i16; 64] = [
1003 47, 47, 47, 47, 45, 43, 43, 43,
1004 43, 43, 42, 41, 41, 40, 40, 40,
1005 40, 35, 35, 35, 35, 33, 33, 33,
1006 33, 32, 32, 32, 27, 27, 26, 26,
1007 25, 25, 24, 24, 23, 23, 19, 19,
1008 19, 19, 18, 18, 17, 16, 16, 16,
1009 16, 16, 15, 11, 11, 11, 10, 10,
1010 9, 8, 7, 5, 3, 3, 2, 2
1011];
1012const VP56_AC_QUANTS: [i16; 64] = [
1013 94, 92, 90, 88, 86, 82, 78, 74,
1014 70, 66, 62, 58, 54, 53, 52, 51,
1015 50, 49, 48, 47, 46, 45, 44, 43,
1016 42, 40, 39, 37, 36, 35, 34, 33,
1017 32, 31, 30, 29, 28, 27, 26, 25,
1018 24, 23, 22, 21, 20, 19, 18, 17,
1019 16, 15, 14, 13, 12, 11, 10, 9,
1020 8, 7, 6, 5, 4, 3, 2, 1
1021];
1022
1023const VP56_FILTER_LIMITS: [u8; 64] = [
1024 14, 14, 13, 13, 12, 12, 10, 10,
1025 10, 10, 8, 8, 8, 8, 8, 8,
1026 8, 8, 8, 8, 8, 8, 8, 8,
1027 8, 8, 8, 8, 8, 8, 8, 8,
1028 8, 8, 8, 8, 7, 7, 7, 7,
1029 7, 7, 6, 6, 6, 6, 6, 6,
1030 5, 5, 5, 5, 4, 4, 4, 4,
1031 4, 4, 4, 3, 3, 3, 3, 2
1032];
1033
1034const VP56_MODE_VQ: [[[u8; 20]; 16]; 3] = [
1035 [
1036 [ 9, 15, 32, 25, 7, 19, 9, 21, 1, 12, 14, 12, 3, 18, 14, 23, 3, 10, 0, 4 ],
1037 [ 48, 39, 1, 2, 11, 27, 29, 44, 7, 27, 1, 4, 0, 3, 1, 6, 1, 2, 0, 0 ],
1038 [ 21, 32, 1, 2, 4, 10, 32, 43, 6, 23, 2, 3, 1, 19, 1, 6, 12, 21, 0, 7 ],
1039 [ 69, 83, 0, 0, 0, 2, 10, 29, 3, 12, 0, 1, 0, 3, 0, 3, 2, 2, 0, 0 ],
1040 [ 11, 20, 1, 4, 18, 36, 43, 48, 13, 35, 0, 2, 0, 5, 3, 12, 1, 2, 0, 0 ],
1041 [ 70, 44, 0, 1, 2, 10, 37, 46, 8, 26, 0, 2, 0, 2, 0, 2, 0, 1, 0, 0 ],
1042 [ 8, 15, 0, 1, 8, 21, 74, 53, 22, 42, 0, 1, 0, 2, 0, 3, 1, 2, 0, 0 ],
1043 [ 141, 42, 0, 0, 1, 4, 11, 24, 1, 11, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0 ],
1044 [ 8, 19, 4, 10, 24, 45, 21, 37, 9, 29, 0, 3, 1, 7, 11, 25, 0, 2, 0, 1 ],
1045 [ 46, 42, 0, 1, 2, 10, 54, 51, 10, 30, 0, 2, 0, 2, 0, 1, 0, 1, 0, 0 ],
1046 [ 28, 32, 0, 0, 3, 10, 75, 51, 14, 33, 0, 1, 0, 2, 0, 1, 1, 2, 0, 0 ],
1047 [ 100, 46, 0, 1, 3, 9, 21, 37, 5, 20, 0, 1, 0, 2, 1, 2, 0, 1, 0, 0 ],
1048 [ 27, 29, 0, 1, 9, 25, 53, 51, 12, 34, 0, 1, 0, 3, 1, 5, 0, 2, 0, 0 ],
1049 [ 80, 38, 0, 0, 1, 4, 69, 33, 5, 16, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1050 [ 16, 20, 0, 0, 2, 8, 104, 49, 15, 33, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1051 [ 194, 16, 0, 0, 1, 1, 1, 9, 1, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
1052 ], [
1053 [ 41, 22, 1, 0, 1, 31, 0, 0, 0, 0, 0, 1, 1, 7, 0, 1, 98, 25, 4, 10 ],
1054 [ 123, 37, 6, 4, 1, 27, 0, 0, 0, 0, 5, 8, 1, 7, 0, 1, 12, 10, 0, 2 ],
1055 [ 26, 14, 14, 12, 0, 24, 0, 0, 0, 0, 55, 17, 1, 9, 0, 36, 5, 7, 1, 3 ],
1056 [ 209, 5, 0, 0, 0, 27, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1057 [ 2, 5, 4, 5, 0, 121, 0, 0, 0, 0, 0, 3, 2, 4, 1, 4, 2, 2, 0, 1 ],
1058 [ 175, 5, 0, 1, 0, 48, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 1, 0, 0 ],
1059 [ 83, 5, 2, 3, 0, 102, 0, 0, 0, 0, 1, 3, 0, 2, 0, 1, 0, 0, 0, 0 ],
1060 [ 233, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 ],
1061 [ 34, 16, 112, 21, 1, 28, 0, 0, 0, 0, 6, 8, 1, 7, 0, 3, 2, 5, 0, 2 ],
1062 [ 159, 35, 2, 2, 0, 25, 0, 0, 0, 0, 3, 6, 0, 5, 0, 1, 4, 4, 0, 1 ],
1063 [ 75, 39, 5, 7, 2, 48, 0, 0, 0, 0, 3, 11, 2, 16, 1, 4, 7, 10, 0, 2 ],
1064 [ 212, 21, 0, 1, 0, 9, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 0, 0 ],
1065 [ 4, 2, 0, 0, 0, 172, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 0, 0 ],
1066 [ 187, 22, 1, 1, 0, 17, 0, 0, 0, 0, 3, 6, 0, 4, 0, 1, 4, 4, 0, 1 ],
1067 [ 133, 6, 1, 2, 1, 70, 0, 0, 0, 0, 0, 2, 0, 4, 0, 3, 1, 1, 0, 0 ],
1068 [ 251, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
1069 ], [
1070 [ 2, 3, 2, 3, 0, 2, 0, 2, 0, 0, 11, 4, 1, 4, 0, 2, 3, 2, 0, 4 ],
1071 [ 49, 46, 3, 4, 7, 31, 42, 41, 0, 0, 2, 6, 1, 7, 1, 4, 2, 4, 0, 1 ],
1072 [ 26, 25, 1, 1, 2, 10, 67, 39, 0, 0, 1, 1, 0, 14, 0, 2, 31, 26, 1, 6 ],
1073 [ 103, 46, 1, 2, 2, 10, 33, 42, 0, 0, 1, 4, 0, 3, 0, 1, 1, 3, 0, 0 ],
1074 [ 14, 31, 9, 13, 14, 54, 22, 29, 0, 0, 2, 6, 4, 18, 6, 13, 1, 5, 0, 1 ],
1075 [ 85, 39, 0, 0, 1, 9, 69, 40, 0, 0, 0, 1, 0, 3, 0, 1, 2, 3, 0, 0 ],
1076 [ 31, 28, 0, 0, 3, 14, 130, 34, 0, 0, 0, 1, 0, 3, 0, 1, 3, 3, 0, 1 ],
1077 [ 171, 25, 0, 0, 1, 5, 25, 21, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 ],
1078 [ 17, 21, 68, 29, 6, 15, 13, 22, 0, 0, 6, 12, 3, 14, 4, 10, 1, 7, 0, 3 ],
1079 [ 51, 39, 0, 1, 2, 12, 91, 44, 0, 0, 0, 2, 0, 3, 0, 1, 2, 3, 0, 1 ],
1080 [ 81, 25, 0, 0, 2, 9, 106, 26, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1081 [ 140, 37, 0, 1, 1, 8, 24, 33, 0, 0, 1, 2, 0, 2, 0, 1, 1, 2, 0, 0 ],
1082 [ 14, 23, 1, 3, 11, 53, 90, 31, 0, 0, 0, 3, 1, 5, 2, 6, 1, 2, 0, 0 ],
1083 [ 123, 29, 0, 0, 1, 7, 57, 30, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 ],
1084 [ 13, 14, 0, 0, 4, 20, 175, 20, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0 ],
1085 [ 202, 23, 0, 0, 1, 3, 2, 9, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ],
1086 ]
1087];
1088