]> git.nihav.org Git - nihav.git/blame - nihav-duck/src/codecs/vp5.rs
add IVF demuxer for VP8 test samples
[nihav.git] / nihav-duck / src / codecs / vp5.rs
CommitLineData
3584b223
KS
1use nihav_core::codecs::*;
2use nihav_core::io::bitreader::*;
b4d5b851 3use nihav_codec_support::codecs::{MV, ZIGZAG};
3584b223
KS
4use super::vpcommon::*;
5use super::vp56::*;
6
7struct VP5BR {}
8
9impl VP5BR {
10 fn new() -> Self {
11 Self {}
12 }
13}
14
15impl 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 }
d24468d9 36
3584b223
KS
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 }
d24468d9 196
3584b223
KS
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) {
ab5baaf1 223 (mv.x >> 1, mv.y >> 1, mv.x & 1, mv.y & 1)
3584b223 224 } else {
6d3946fe 225 (mv.x >> 2, mv.y >> 2, if (mv.x & 3) != 0 { 1 } else { 0 }, if (mv.y & 3) != 0 { 1 } else { 0 })
ab5baaf1
KS
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
3584b223 232 };
3584b223
KS
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
238struct VP5Decoder {
239 dec: VP56Decoder,
240 info: NACodecInfoRef,
241 br: VP5BR,
242}
243
244impl 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
254impl 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);
47933c6d 258 let myinfo = NACodecTypeInfo::Video(myvinfo);
3584b223
KS
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 }
f9be4e75
KS
276 fn flush(&mut self) {
277 self.dec.flush();
278 }
3584b223
KS
279}
280
7d57ae2f
KS
281impl 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
ac818eac 287pub fn get_decoder() -> Box<dyn NADecoder + Send> {
3584b223
KS
288 Box::new(VP5Decoder::new())
289}
290
291#[cfg(test)]
292mod test {
293 use nihav_core::codecs::RegisteredDecoders;
294 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 295 use nihav_codec_support::test::dec_video::*;
78fb6560 296 use crate::duck_register_all_decoders;
e64739f8 297 use nihav_commonfmt::generic_register_all_demuxers;
3584b223
KS
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();
78fb6560 304 duck_register_all_decoders(&mut dec_reg);
3584b223
KS
305
306 let file = "assets/Duck/Cell-140.vp5";
307 //let file = "assets/Duck/Chocolat-500.vp5";
d5e94eaf
KS
308 test_decoding("avi", "vp5", file, Some(96), &dmx_reg, &dec_reg,
309 ExpectedTestResult::MD5([0x9ad78b0f, 0xed988ead, 0x88ed2ea9, 0xcdb75cdf]));
3584b223
KS
310 }
311}
312
313const 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
365const 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
404const 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];