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