rename register_all_codecs to register_all_decoders
[nihav.git] / nihav-duck / src / codecs / vp5.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::bitreader::*;
3 use nihav_codec_support::codecs::{MV, ZIGZAG};
4 use super::vpcommon::*;
5 use super::vp56::*;
6
7 struct VP5BR {}
8
9 impl VP5BR {
10 fn new() -> Self {
11 Self {}
12 }
13 }
14
15 impl VP56Parser for VP5BR {
16 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header> {
17 let mut hdr = VP56Header::default();
18 hdr.is_intra = !bc.read_bool();
19 hdr.is_golden = hdr.is_intra;
20 bc.read_bool();
21 hdr.quant = bc.read_bits(6) as u8;
22 if hdr.is_intra {
23 hdr.version = bc.read_bits(13) as u8;
24 validate!(hdr.version == 5);
25 hdr.profile = bc.read_bits(2) as u8;
26 hdr.interlaced = bc.read_bool();
27 validate!(!hdr.interlaced);
28 hdr.mb_h = bc.read_bits(8) as u8;
29 hdr.mb_w = bc.read_bits(8) as u8;
30 hdr.disp_h = bc.read_bits(8) as u8;
31 hdr.disp_w = bc.read_bits(8) as u8;
32 validate!((hdr.mb_h > 0) && (hdr.mb_w > 0) && (hdr.disp_w > 0) && (hdr.disp_h > 0));
33 validate!((hdr.disp_w <= hdr.mb_w) && (hdr.disp_h <= hdr.mb_h));
34 hdr.scale = bc.read_bits(2) as u8;
35 }
36
37 Ok(hdr)
38 }
39 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16 {
40 if bc.read_prob(model.nz_prob) {
41 let sign = bc.read_prob(model.sign_prob);
42 let b0 = bc.read_prob(model.raw_probs[0]) as i16;
43 let b1 = bc.read_prob(model.raw_probs[1]) as i16;
44 let top: i16 = vp_tree!(bc, model.tree_probs[0],
45 vp_tree!(bc, model.tree_probs[1],
46 vp_tree!(bc, model.tree_probs[2], 0, 1),
47 vp_tree!(bc, model.tree_probs[3], 2, 3)
48 ),
49 vp_tree!(bc, model.tree_probs[4],
50 vp_tree!(bc, model.tree_probs[5], 4, 5),
51 vp_tree!(bc, model.tree_probs[6], 6, 7)
52 )
53 );
54 let val = (top << 2) | (b1 << 1) | b0;
55 if !sign {
56 val
57 } else {
58 -val
59 }
60 } else {
61 0
62 }
63 }
64 fn reset_models(&self, models: &mut VP56Models) {
65 for mdl in models.mv_models.iter_mut() {
66 mdl.nz_prob = 128;
67 mdl.sign_prob = 128;
68 mdl.raw_probs[0] = 85;
69 mdl.raw_probs[1] = 128;
70 mdl.tree_probs = [128; 7];
71 }
72 }
73 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()> {
74 const HAS_NZ_PROB: [u8; 2] = [ 243, 235 ];
75 const HAS_SIGN_PROB: [u8; 2] = [ 220, 211 ];
76 const HAS_RAW0_PROB: [u8; 2] = [ 251, 246 ];
77 const HAS_RAW1_PROB: [u8; 2] = [ 253, 249 ];
78 const HAS_TREE_PROB: [[u8; 7]; 2] = [
79 [ 237, 232, 241, 245, 247, 251, 253 ],
80 [ 234, 231, 248, 249, 252, 252, 254 ]
81 ];
82 for comp in 0..2 {
83 if bc.read_prob(HAS_NZ_PROB[comp]) {
84 models[comp].nz_prob = bc.read_probability();
85 }
86 if bc.read_prob(HAS_SIGN_PROB[comp]) {
87 models[comp].sign_prob = bc.read_probability();
88 }
89 if bc.read_prob(HAS_RAW0_PROB[comp]) {
90 models[comp].raw_probs[0] = bc.read_probability();
91 }
92 if bc.read_prob(HAS_RAW1_PROB[comp]) {
93 models[comp].raw_probs[1] = bc.read_probability();
94 }
95 }
96 for comp in 0..2 {
97 for i in 0..7 {
98 if bc.read_prob(HAS_TREE_PROB[comp][i]) {
99 models[comp].tree_probs[i] = bc.read_probability();
100 }
101 }
102 }
103 Ok(())
104 }
105 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()> {
106 const COEF_PROBS: [[u8; 11]; 2] = [
107 [ 146, 197, 181, 207, 232, 243, 238, 251, 244, 250, 249 ],
108 [ 179, 219, 214, 240, 250, 254, 244, 254, 254, 254, 254 ]
109 ];
110
111 let mut def_prob = [128u8; 11];
112 for plane in 0..2 {
113 for i in 0..11 {
114 if bc.read_prob(COEF_PROBS[plane][i]) {
115 def_prob[i] = bc.read_probability();
116 models.coeff_models[plane].dc_value_probs[i] = def_prob[i];
117 } else if is_intra {
118 models.coeff_models[plane].dc_value_probs[i] = def_prob[i];
119 }
120 }
121 }
122 for ctype in 0..3 {
123 for plane in 0..2 {
124 for group in 0..6 {
125 for i in 0..11 {
126 if bc.read_prob(VP5_AC_PROBS[ctype][plane][group][i]) {
127 def_prob[i] = bc.read_probability();
128 models.coeff_models[plane].ac_val_probs[ctype][group][i] = def_prob[i];
129 } else if is_intra {
130 models.coeff_models[plane].ac_val_probs[ctype][group][i] = def_prob[i];
131 }
132 }
133 }
134 }
135 }
136 for plane in 0..2 {
137 let mdl = &mut models.coeff_models[plane];
138 for i in 0..6 {
139 for j in 0..6 {
140 for k in 0..5 {
141 mdl.dc_token_probs[i][j][k] = rescale_prob(mdl.dc_value_probs[k], &VP5_DC_WEIGHTS[k][i][j], 254);
142 }
143 }
144 }
145 for ctype in 0..3 {
146 for group in 0..3 {
147 for i in 0..6 {
148 for j in 0..5 {
149 mdl.ac_type_probs[ctype][group][i][j] = rescale_prob(mdl.ac_val_probs[ctype][group][j], &VP5_AC_WEIGHTS[ctype][group][j][i], 254);
150 }
151 }
152 }
153 }
154 }
155 Ok(())
156 }
157 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, _vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()> {
158 const COEF_GROUPS: [u8; 64] = [
159 0, 0, 1, 1, 2, 1, 1, 2,
160 2, 1, 1, 2, 2, 2, 1, 2,
161 2, 2, 2, 2, 1, 1, 2, 2,
162 3, 3, 4, 3, 4, 4, 4, 3,
163 3, 3, 3, 3, 4, 3, 3, 3,
164 4, 4, 4, 4, 4, 3, 3, 4,
165 4, 4, 3, 4, 4, 4, 4, 4,
166 4, 4, 5, 5, 5, 5, 5, 5
167 ];
168
169 let mut ctype = 1;
170 let left_ctx = fstate.coeff_cat[fstate.ctx_idx][0] as usize;
171 let top_ctx = fstate.top_ctx as usize;
172
173 let mut val_probs: &[u8; 11] = &model.dc_value_probs;
174 let mut tok_probs: &[u8] = &model.dc_token_probs[left_ctx][top_ctx];
175 let mut idx = 0;
176 loop {
177 let token = vp_tree!(bc, tok_probs[0],
178 if ctype != 0 { vp_tree!(bc, tok_probs[1], break, 0) } else { 0 },
179 vp_tree!(bc, tok_probs[2],
180 1,
181 vp_tree!(bc, tok_probs[3],
182 vp_tree!(bc, tok_probs[4], 2,
183 vp_tree!(bc, val_probs[5], 3, 4)),
184 TOKEN_LARGE)));
185 let val = expand_token_bc(bc, val_probs, token, 5);
186 ctype = token.min(2) as usize;
187 if token < TOKEN_LARGE {
188 fstate.coeff_cat[fstate.ctx_idx][idx] = token.min(3);
189 } else {
190 fstate.coeff_cat[fstate.ctx_idx][idx] = 4;
191 }
192 coeffs[ZIGZAG[idx]] = val;
193 if idx > 0 {
194 coeffs[ZIGZAG[idx]] *= fstate.ac_quant;
195 }
196
197 idx += 1;
198 if idx >= 64 {
199 break;
200 }
201 let group = COEF_GROUPS[idx] as usize;
202 val_probs = &model.ac_val_probs[ctype][group];
203 tok_probs = if group > 2 { val_probs
204 } else {
205 let ctx = fstate.coeff_cat[fstate.ctx_idx][idx] as usize;
206 &model.ac_type_probs[ctype][group][ctx]
207 };
208 }
209 let end = fstate.last_idx[fstate.ctx_idx].min(24);
210 fstate.last_idx[fstate.ctx_idx] = idx;
211 for i in idx..end {
212 fstate.coeff_cat[fstate.ctx_idx][i] = 5;
213 }
214 fstate.top_ctx = fstate.coeff_cat[fstate.ctx_idx][0];
215
216 Ok(())
217 }
218 fn decode_block_huff(&self, _br: &mut BitReader, _coeffs: &mut [i16; 64], _vp6model: &VP6Models, _model: &VP6HuffModels, _fstate: &mut FrameState) -> DecoderResult<()> {
219 unreachable!();
220 }
221 fn mc_block(&self, dst: &mut NASimpleVideoFrame<u8>, mc_buf: NAVideoBufferRef<u8>, src: NAVideoBufferRef<u8>, plane: usize, x: usize, y: usize, mv: MV, loop_str: i16) {
222 let (sx, sy, mx, my) = if (plane != 1) && (plane != 2) {
223 (mv.x >> 1, mv.y >> 1, mv.x & 1, mv.y & 1)
224 } else {
225 (mv.x >> 2, mv.y >> 2, if (mv.x & 3) != 0 { 1 } else { 0 }, if (mv.y & 3) != 0 { 1 } else { 0 })
226 };
227 let mode1 = (mx as usize) + (my as usize) * 2;
228 let mode = if (mode1 == 3) && (mv.x ^ mv.y < 0) {
229 4
230 } else {
231 mode1
232 };
233 vp_copy_block(dst, src, plane, x, y, sx, sy, 0, 1, loop_str,
234 mode, VP3_INTERP_FUNCS, mc_buf);
235 }
236 }
237
238 struct VP5Decoder {
239 dec: VP56Decoder,
240 info: NACodecInfoRef,
241 br: VP5BR,
242 }
243
244 impl VP5Decoder {
245 fn new() -> Self {
246 Self {
247 dec: VP56Decoder::new(5, false, true),
248 info: NACodecInfoRef::default(),
249 br: VP5BR::new(),
250 }
251 }
252 }
253
254 impl NADecoder for VP5Decoder {
255 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
256 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
257 let myvinfo = NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, YUV420_FORMAT);
258 let myinfo = NACodecTypeInfo::Video(myvinfo);
259 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
260 self.dec.init(supp, myvinfo)?;
261 Ok(())
262 } else {
263 Err(DecoderError::InvalidData)
264 }
265 }
266 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
267 let src = pkt.get_buffer();
268
269 let (bufinfo, ftype) = self.dec.decode_frame(supp, src.as_slice(), &mut self.br)?;
270
271 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
272 frm.set_keyframe(ftype == FrameType::I);
273 frm.set_frame_type(ftype);
274 Ok(frm.into_ref())
275 }
276 fn flush(&mut self) {
277 self.dec.flush();
278 }
279 }
280
281 impl NAOptionHandler for VP5Decoder {
282 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
283 fn set_options(&mut self, _options: &[NAOption]) { }
284 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
285 }
286
287 pub fn get_decoder() -> Box<NADecoder + Send> {
288 Box::new(VP5Decoder::new())
289 }
290
291 #[cfg(test)]
292 mod test {
293 use nihav_core::codecs::RegisteredDecoders;
294 use nihav_core::demuxers::RegisteredDemuxers;
295 use nihav_codec_support::test::dec_video::*;
296 use crate::duck_register_all_decoders;
297 use nihav_commonfmt::generic_register_all_demuxers;
298
299 #[test]
300 fn test_vp5() {
301 let mut dmx_reg = RegisteredDemuxers::new();
302 generic_register_all_demuxers(&mut dmx_reg);
303 let mut dec_reg = RegisteredDecoders::new();
304 duck_register_all_decoders(&mut dec_reg);
305
306 let file = "assets/Duck/Cell-140.vp5";
307 //let file = "assets/Duck/Chocolat-500.vp5";
308 test_decoding("avi", "vp5", file, Some(96), &dmx_reg, &dec_reg,
309 ExpectedTestResult::MD5([0x9ad78b0f, 0xed988ead, 0x88ed2ea9, 0xcdb75cdf]));
310 }
311 }
312
313 const VP5_AC_PROBS: [[[[u8; 11]; 6]; 2]; 3] = [
314 [
315 [
316 [ 227, 246, 230, 247, 244, 254, 254, 254, 254, 254, 254 ],
317 [ 202, 254, 209, 231, 231, 249, 249, 253, 254, 254, 254 ],
318 [ 206, 254, 225, 242, 241, 251, 253, 254, 254, 254, 254 ],
319 [ 235, 254, 241, 253, 252, 254, 254, 254, 254, 254, 254 ],
320 [ 234, 254, 248, 254, 254, 254, 254, 254, 254, 254, 254 ],
321 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ]
322 ], [
323 [ 240, 254, 248, 254, 254, 254, 254, 254, 254, 254, 254 ],
324 [ 238, 254, 240, 253, 254, 254, 254, 254, 254, 254, 254 ],
325 [ 244, 254, 251, 254, 254, 254, 254, 254, 254, 254, 254 ],
326 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
327 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
328 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ]
329 ]
330 ], [
331 [
332 [ 206, 203, 227, 239, 247, 254, 253, 254, 254, 254, 254 ],
333 [ 207, 199, 220, 236, 243, 252, 252, 254, 254, 254, 254 ],
334 [ 212, 219, 230, 243, 244, 253, 252, 254, 254, 254, 254 ],
335 [ 236, 237, 247, 252, 253, 254, 254, 254, 254, 254, 254 ],
336 [ 240, 240, 248, 254, 254, 254, 254, 254, 254, 254, 254 ],
337 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ]
338 ], [
339 [ 230, 233, 249, 254, 254, 254, 254, 254, 254, 254, 254 ],
340 [ 238, 238, 250, 254, 254, 254, 254, 254, 254, 254, 254 ],
341 [ 248, 251, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
342 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
343 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
344 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ]
345 ]
346 ], [
347 [
348 [ 225, 239, 227, 231, 244, 253, 243, 254, 254, 253, 254 ],
349 [ 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 254 ],
350 [ 235, 249, 238, 240, 251, 254, 249, 254, 253, 253, 254 ],
351 [ 249, 253, 251, 250, 254, 254, 254, 254, 254, 254, 254 ],
352 [ 251, 250, 249, 254, 254, 254, 254, 254, 254, 254, 254 ],
353 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ]
354 ], [
355 [ 243, 244, 250, 250, 254, 254, 254, 254, 254, 254, 254 ],
356 [ 249, 248, 250, 253, 254, 254, 254, 254, 254, 254, 254 ],
357 [ 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
358 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
359 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ],
360 [ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 ]
361 ]
362 ]
363 ];
364
365 const VP5_DC_WEIGHTS: [[[[i16; 2]; 6]; 6]; 5] = [
366 [
367 [ [154, 61], [141, 54], [ 90, 45], [ 54, 34], [ 54, 13], [128, 109] ],
368 [ [136, 54], [148, 45], [ 92, 41], [ 54, 33], [ 51, 15], [ 87, 113] ],
369 [ [ 87, 44], [ 97, 40], [ 67, 36], [ 46, 29], [ 41, 15], [ 64, 80] ],
370 [ [ 59, 33], [ 61, 31], [ 51, 28], [ 44, 22], [ 33, 12], [ 49, 63] ],
371 [ [ 69, 12], [ 59, 16], [ 46, 14], [ 31, 13], [ 26, 6], [ 92, 26] ],
372 [ [128, 108], [ 77, 119], [ 54, 84], [ 26, 71], [ 87, 19], [ 95, 155] ]
373 ], [
374 [ [154, 4], [182, 0], [159, -8], [128, -5], [143, -5], [187, 55] ],
375 [ [182, 0], [228, -3], [187, -7], [174, -9], [189, -11], [169, 79] ],
376 [ [161, -9], [192, -8], [187, -9], [169, -10], [136, -9], [184, 40] ],
377 [ [164, -11], [179, -10], [174, -10], [161, -10], [115, -7], [197, 20] ],
378 [ [195, -11], [195, -11], [146, -10], [110, -6], [ 95, -4], [195, 39] ],
379 [ [182, 55], [172, 77], [177, 37], [169, 29], [172, 52], [ 92, 162] ]
380 ], [
381 [ [174, 80], [164, 80], [ 95, 80], [ 46, 66], [ 56, 24], [ 36, 193] ],
382 [ [164, 80], [166, 77], [105, 76], [ 49, 68], [ 46, 31], [ 49, 186] ],
383 [ [ 97, 78], [110, 74], [ 72, 72], [ 44, 60], [ 33, 30], [ 69, 131] ],
384 [ [ 61, 61], [ 69, 63], [ 51, 57], [ 31, 48], [ 26, 27], [ 64, 89] ],
385 [ [ 67, 23], [ 51, 32], [ 36, 33], [ 26, 28], [ 20, 12], [ 44, 68] ],
386 [ [ 26, 197], [ 41, 189], [ 61, 129], [ 28, 103], [ 49, 52], [-12, 245] ]
387 ], [
388 [ [102, 141], [ 79, 166], [ 72, 162], [ 97, 125], [179, 4], [307, 0] ],
389 [ [ 72, 168], [ 69, 175], [ 84, 160], [105, 127], [148, 34], [310, 0] ],
390 [ [ 84, 151], [ 82, 161], [ 87, 153], [ 87, 135], [115, 51], [317, 0] ],
391 [ [ 97, 125], [102, 131], [105, 125], [ 87, 122], [ 84, 64], [ 54, 184] ],
392 [ [166, 18], [146, 43], [125, 51], [ 90, 64], [ 95, 7], [ 38, 154] ],
393 [ [294, 0], [ 13, 225], [ 10, 225], [ 67, 168], [ 0, 167], [161, 94] ]
394 ], [
395 [ [172, 76], [172, 75], [136, 80], [ 64, 98], [ 74, 67], [315, 0] ],
396 [ [169, 76], [207, 56], [164, 66], [ 97, 80], [ 67, 72], [328, 0] ],
397 [ [136, 80], [187, 53], [154, 62], [ 72, 85], [ -2, 105], [305, 0] ],
398 [ [ 74, 91], [128, 64], [113, 64], [ 61, 77], [ 41, 75], [259, 0] ],
399 [ [ 46, 84], [ 51, 81], [ 28, 89], [ 31, 78], [ 23, 77], [202, 0] ],
400 [ [323, 0], [323, 0], [300, 0], [236, 0], [195, 0], [328, 0] ]
401 ]
402 ];
403
404 const VP5_AC_WEIGHTS: [[[[[i16; 2]; 6]; 5]; 3]; 3] = [
405 [
406 [
407 [ [276, 0], [238, 0], [195, 0], [156, 0], [113, 0], [274, 0] ],
408 [ [ 0, 1], [ 0, 1], [ 0, 1], [ 0, 1], [ 0, 1], [ 0, 1] ],
409 [ [192, 59], [182, 50], [141, 48], [110, 40], [ 92, 19], [125,128] ],
410 [ [169, 87], [169, 83], [184, 62], [220, 16], [184, 0], [264, 0] ],
411 [ [212, 40], [212, 36], [169, 49], [174, 27], [ 8,120], [182, 71] ]
412 ], [
413 [ [259, 10], [197, 19], [143, 22], [123, 16], [110, 8], [133, 88] ],
414 [ [ 0, 1], [256, 0], [ 0, 1], [ 0, 1], [ 0, 1], [ 0, 1] ],
415 [ [207, 46], [187, 50], [ 97, 83], [ 23,100], [ 41, 56], [ 56,188] ],
416 [ [166, 90], [146,108], [161, 88], [136, 95], [174, 0], [266, 0] ],
417 [ [264, 7], [243, 18], [184, 43], [-14,154], [ 20,112], [ 20,199] ]
418 ], [
419 [ [230, 26], [197, 22], [159, 20], [146, 12], [136, 4], [ 54,162] ],
420 [ [ 0, 1], [ 0, 1], [ 0, 1], [ 0, 1], [ 0, 1], [ 0, 1] ],
421 [ [192, 59], [156, 72], [ 84,101], [ 49,101], [ 79, 47], [ 79,167] ],
422 [ [138,115], [136,116], [166, 80], [238, 0], [195, 0], [261, 0] ],
423 [ [225, 33], [205, 42], [159, 61], [ 79, 96], [ 92, 66], [ 28,195] ]
424 ]
425 ], [
426 [
427 [ [200, 37], [197, 18], [159, 13], [143, 7], [102, 5], [123,126] ],
428 [ [197, 3], [220, -9], [210,-12], [187, -6], [151, -2], [174, 80] ],
429 [ [200, 53], [187, 47], [159, 40], [118, 38], [100, 18], [141,111] ],
430 [ [179, 78], [166, 86], [197, 50], [207, 27], [187, 0], [115,139] ],
431 [ [218, 34], [220, 29], [174, 46], [128, 61], [ 54, 89], [187, 65] ]
432 ], [
433 [ [238, 14], [197, 18], [125, 26], [ 90, 25], [ 82, 13], [161, 86] ],
434 [ [189, 1], [205, -2], [156, -4], [143, -4], [146, -4], [172, 72] ],
435 [ [230, 31], [192, 45], [102, 76], [ 38, 85], [ 56, 41], [ 64,173] ],
436 [ [166, 91], [141,111], [128,116], [118,109], [177, 0], [ 23,222] ],
437 [ [253, 14], [236, 21], [174, 49], [ 33,118], [ 44, 93], [ 23,187] ]
438 ], [
439 [ [218, 28], [179, 28], [118, 35], [ 95, 30], [ 72, 24], [128,108] ],
440 [ [187, 1], [174, -1], [125, -1], [110, -1], [108, -1], [202, 52] ],
441 [ [197, 53], [146, 75], [ 46,118], [ 33,103], [ 64, 50], [118,126] ],
442 [ [138,114], [128,122], [161, 86], [243, -6], [195, 0], [ 38,210] ],
443 [ [215, 39], [179, 58], [ 97,101], [ 95, 85], [ 87, 70], [ 69,152] ]
444 ]
445 ], [
446 [
447 [ [236, 24], [205, 18], [172, 12], [154, 6], [125, 1], [169, 75] ],
448 [ [187, 4], [230, -2], [228, -4], [236, -4], [241, -2], [192, 66] ],
449 [ [200, 46], [187, 42], [159, 34], [136, 25], [105, 10], [179, 62] ],
450 [ [207, 55], [192, 63], [192, 54], [195, 36], [177, 1], [143, 98] ],
451 [ [225, 27], [207, 34], [200, 30], [131, 57], [ 97, 60], [197, 45] ]
452 ], [
453 [ [271, 8], [218, 13], [133, 19], [ 90, 19], [ 72, 7], [182, 51] ],
454 [ [179, 1], [225, -1], [154, -2], [110, -1], [ 92, 0], [195, 41] ],
455 [ [241, 26], [189, 40], [ 82, 64], [ 33, 60], [ 67, 17], [120, 94] ],
456 [ [192, 68], [151, 94], [146, 90], [143, 72], [161, 0], [113,128] ],
457 [ [256, 12], [218, 29], [166, 48], [ 44, 99], [ 31, 87], [148, 78] ]
458 ], [
459 [ [238, 20], [184, 22], [113, 27], [ 90, 22], [ 74, 9], [192, 37] ],
460 [ [184, 0], [215, -1], [141, -1], [ 97, 0], [ 49, 0], [264, 13] ],
461 [ [182, 51], [138, 61], [ 95, 63], [ 54, 59], [ 64, 25], [200, 45] ],
462 [ [179, 75], [156, 87], [174, 65], [177, 44], [174, 0], [164, 85] ],
463 [ [195, 45], [148, 65], [105, 79], [ 95, 72], [ 87, 60], [169, 63] ]
464 ]
465 ]
466 ];