]> git.nihav.org Git - nihav.git/blame_incremental - nihav-qt/src/codecs/svq1.rs
aac: fix intensity stereo reconstruction for ms_mask_present=0 case
[nihav.git] / nihav-qt / src / codecs / svq1.rs
... / ...
CommitLineData
1use nihav_core::codecs::*;
2use nihav_core::io::bitreader::*;
3use nihav_core::io::codebook::*;
4use nihav_core::io::intcode::*;
5use nihav_codec_support::codecs::{MV, ZERO_MV};
6use nihav_codec_support::codecs::blockdsp::*;
7
8use super::svq1data::*;
9
10#[derive(Clone,Copy,Debug,PartialEq)]
11enum SVQ1FrameType {
12 I,
13 P,
14 Drop,
15}
16
17#[derive(Clone,Copy,Debug,PartialEq)]
18enum BlockType {
19 Intra,
20 Skip,
21 OneMV,
22 FourMV,
23}
24
25#[derive(Clone,Copy,Debug,PartialEq)]
26#[allow(clippy::enum_variant_names)]
27enum BlockDiv {
28 Div16x16,
29 Div16x8,
30 Div8x8,
31 Div8x4,
32 Div4x4,
33 Div4x2,
34}
35
36impl BlockDiv {
37 fn is_final(self) -> bool { self == BlockDiv::Div4x2 }
38 fn split(self) -> (Self, usize, usize) {
39 match self {
40 BlockDiv::Div16x16 => (BlockDiv::Div16x8, 0, 8),
41 BlockDiv::Div16x8 => (BlockDiv::Div8x8, 8, 0),
42 BlockDiv::Div8x8 => (BlockDiv::Div8x4, 0, 4),
43 BlockDiv::Div8x4 => (BlockDiv::Div4x4, 4, 0),
44 BlockDiv::Div4x4 => (BlockDiv::Div4x2, 0, 2),
45 BlockDiv::Div4x2 => unreachable!(),
46 }
47 }
48 fn get_size(self) -> (usize, usize) {
49 match self {
50 BlockDiv::Div16x16 => (16, 16),
51 BlockDiv::Div16x8 => (16, 8),
52 BlockDiv::Div8x8 => ( 8, 8),
53 BlockDiv::Div8x4 => ( 8, 4),
54 BlockDiv::Div4x4 => ( 4, 4),
55 BlockDiv::Div4x2 => ( 4, 2),
56 }
57 }
58 fn get_level(self) -> usize {
59 match self {
60 BlockDiv::Div16x16 => 5,
61 BlockDiv::Div16x8 => 4,
62 BlockDiv::Div8x8 => 3,
63 BlockDiv::Div8x4 => 2,
64 BlockDiv::Div4x4 => 1,
65 BlockDiv::Div4x2 => 0,
66 }
67 }
68}
69
70const BLOCK_TYPES: [BlockType; 4] = [ BlockType::Skip, BlockType::OneMV, BlockType::FourMV, BlockType::Intra ];
71
72impl SVQ1FrameType {
73 fn is_ref(self) -> bool {
74 self != SVQ1FrameType::Drop
75 }
76 fn is_intra(self) -> bool {
77 self == SVQ1FrameType::I
78 }
79 fn to_frame_type(self) -> FrameType {
80 match self {
81 SVQ1FrameType::I => FrameType::I,
82 SVQ1FrameType::P => FrameType::P,
83 SVQ1FrameType::Drop => FrameType::P,
84 }
85 }
86 fn from_id(id: u32) -> DecoderResult<Self> {
87 match id {
88 0 => Ok(SVQ1FrameType::I),
89 1 => Ok(SVQ1FrameType::P),
90 2 => Ok(SVQ1FrameType::Drop),
91 _ => Err(DecoderError::InvalidData),
92 }
93 }
94}
95
96struct SVQ1DescReader {
97 table: &'static [[u8; 2]],
98 bias: i16,
99}
100
101impl CodebookDescReader<i16> for SVQ1DescReader {
102 fn bits(&mut self, idx: usize) -> u8 { self.table[idx][1] }
103 fn code(&mut self, idx: usize) -> u32 { u32::from(self.table[idx][0]) }
104 fn sym(&mut self, idx: usize) -> i16 { (idx as i16) + self.bias }
105 fn len(&mut self) -> usize { self.table.len() }
106}
107
108struct SVQ1InterMeanDescReader {}
109
110impl CodebookDescReader<i16> for SVQ1InterMeanDescReader {
111 fn bits(&mut self, idx: usize) -> u8 { SVQ_INTER_MEAN_CODES[idx][1] as u8 }
112 fn code(&mut self, idx: usize) -> u32 { u32::from(SVQ_INTER_MEAN_CODES[idx][0]) }
113 fn sym(&mut self, idx: usize) -> i16 { (idx as i16) - 256 }
114 fn len(&mut self) -> usize { SVQ_INTER_MEAN_CODES.len() }
115}
116
117struct SVQ1Decoder {
118 info: NACodecInfoRef,
119 width: usize,
120 height: usize,
121 ref_frm: Option<NAVideoBufferRef<u8>>,
122 mvs: Vec<MV>,
123 intra_stages_cb: Vec<Codebook<i16>>,
124 inter_stages_cb: Vec<Codebook<i16>>,
125 intra_mean_cb: Codebook<i16>,
126 inter_mean_cb: Codebook<i16>,
127 mv_cb: Codebook<i16>,
128
129 div_list: [(BlockDiv, usize); 64],
130}
131
132impl SVQ1Decoder {
133 #[allow(clippy::needless_range_loop)]
134 fn new() -> Self {
135 let mut intra_stages_cb = Vec::with_capacity(6);
136 for i in 0..6 {
137 let mut cbd = SVQ1DescReader { table: &SVQ_INTRA_STAGE_CODES[i], bias: -1 };
138 let cb = Codebook::new(&mut cbd, CodebookMode::MSB).unwrap();
139 intra_stages_cb.push(cb);
140 }
141 let mut inter_stages_cb = Vec::with_capacity(6);
142 for i in 0..6 {
143 let mut cbd = SVQ1DescReader { table: &SVQ_INTER_STAGE_CODES[i], bias: -1 };
144 let cb = Codebook::new(&mut cbd, CodebookMode::MSB).unwrap();
145 inter_stages_cb.push(cb);
146 }
147 let mut cbd = SVQ1DescReader { table: &SVQ_INTRA_MEAN_CODES, bias: 0 };
148 let intra_mean_cb = Codebook::new(&mut cbd, CodebookMode::MSB).unwrap();
149 let mut cbd = SVQ1InterMeanDescReader {};
150 let inter_mean_cb = Codebook::new(&mut cbd, CodebookMode::MSB).unwrap();
151 let mut cbd = SVQ1DescReader { table: &SVQ_MV_CODES, bias: 0 };
152 let mv_cb = Codebook::new(&mut cbd, CodebookMode::MSB).unwrap();
153 Self {
154 info: NACodecInfoRef::default(),
155 width: 0,
156 height: 0,
157 ref_frm: None,
158 mvs: Vec::new(),
159 intra_stages_cb, inter_stages_cb, intra_mean_cb, inter_mean_cb, mv_cb,
160 div_list: [(BlockDiv::Div16x16, 0); 64],
161 }
162 }
163 fn read_mv(&self, br: &mut BitReader) -> DecoderResult<MV> {
164 let mut x = br.read_cb(&self.mv_cb)?;
165 if x > 0 && br.read_bool()? {
166 x = -x;
167 }
168 let mut y = br.read_cb(&self.mv_cb)?;
169 if y > 0 && br.read_bool()? {
170 y = -y;
171 }
172 Ok(MV { x, y })
173 }
174 #[allow(clippy::too_many_arguments)]
175 fn pred_mv(&self, x: usize, y: usize, w: usize, mv_idx: usize, mvstride: usize, blk_idx: usize, diff: MV) -> MV {
176 let a_mv = if x > 0 || (blk_idx & 1) != 0 { self.mvs[mv_idx - 1] } else { ZERO_MV };
177 let b_mv = if y > 0 || (blk_idx & 2) != 0 { self.mvs[mv_idx - mvstride] } else { a_mv };
178 let c_mv = match blk_idx {
179 0 => if y > 0 && x + 16 < w { self.mvs[mv_idx + 2 - mvstride] } else { ZERO_MV },
180 1 => if y > 0 && x + 16 < w { self.mvs[mv_idx + 1 - mvstride] } else { ZERO_MV },
181 2 => self.mvs[mv_idx + 1 - mvstride],
182 _ => self.mvs[mv_idx - 1 - mvstride],
183 };
184 let mut new_mv = diff + MV::pred(a_mv, b_mv, c_mv);
185 if new_mv.x >= 32 { new_mv.x -= 64; }
186 else if new_mv.x <= -32 { new_mv.x += 64; }
187 if new_mv.y >= 32 { new_mv.y -= 64; }
188 else if new_mv.y <= -32 { new_mv.y += 64; }
189 new_mv
190 }
191 fn decode_intra_block(&mut self, br: &mut BitReader, dst: &mut [u8], dstride: usize) -> DecoderResult<()> {
192 self.div_list[0] = (BlockDiv::Div16x16, 0);
193 let mut idx = 0;
194 let mut end = 1;
195 while idx < end {
196 let (div, off) = self.div_list[idx];
197 if !div.is_final() && br.read_bool()? {
198 let (ndiv, xoff, yoff) = div.split();
199 self.div_list[end] = (ndiv, off);
200 end += 1;
201 self.div_list[end] = (ndiv, off + xoff + yoff * dstride);
202 end += 1;
203 } else {
204 let level = div.get_level();
205 let stages = br.read_cb(&self.intra_stages_cb[level])?;
206 if level > 3 {
207 validate!(stages <= 0);
208 }
209 let (w, h) = div.get_size();
210 let fill = if stages < 0 { 0 } else { br.read_cb(&self.intra_mean_cb)? } as u8;
211 for line in dst[off..].chunks_mut(dstride).take(h) {
212 for el in line.iter_mut().take(w) {
213 *el = fill;
214 }
215 }
216 if stages > 0 {
217 for stage in 0..(stages as usize) {
218 let idx = br.read(4)? as usize;
219 let src: &[i8] = match div {
220 BlockDiv::Div8x8 => &SVQ_INTRA_CB_8X8[stage * 16 + idx],
221 BlockDiv::Div8x4 => &SVQ_INTRA_CB_8X4[stage * 16 + idx],
222 BlockDiv::Div4x4 => &SVQ_INTRA_CB_4X4[stage * 16 + idx],
223 BlockDiv::Div4x2 => &SVQ_INTRA_CB_4X2[stage * 16 + idx],
224 _ => unreachable!(),
225 };
226 for (line, src) in dst[off..].chunks_mut(dstride).zip(src.chunks(w)) {
227 for x in 0..w {
228 line[x] = (i16::from(line[x]) + i16::from(src[x])).max(0).min(255) as u8;
229 }
230 }
231 }
232 }
233 }
234 idx += 1;
235 }
236 Ok(())
237 }
238 fn decode_inter_block(&mut self, br: &mut BitReader, dst: &mut [u8], dstride: usize) -> DecoderResult<()> {
239 self.div_list[0] = (BlockDiv::Div16x16, 0);
240 let mut idx = 0;
241 let mut end = 1;
242 while idx < end {
243 let (div, off) = self.div_list[idx];
244 if !div.is_final() && br.read_bool()? {
245 let (ndiv, xoff, yoff) = div.split();
246 self.div_list[end] = (ndiv, off);
247 end += 1;
248 self.div_list[end] = (ndiv, off + xoff + yoff * dstride);
249 end += 1;
250 } else {
251 let level = div.get_level();
252 let stages = br.read_cb(&self.inter_stages_cb[level])?;
253 if level > 3 {
254 validate!(stages <= 0);
255 }
256 let (w, h) = div.get_size();
257 let fill = if stages < 0 { 0 } else { br.read_cb(&self.inter_mean_cb)? };
258 if fill != 0 {
259 for line in dst[off..].chunks_mut(dstride).take(h) {
260 for el in line.iter_mut().take(w) {
261 *el = el.wrapping_add(fill as u8);
262 }
263 }
264 }
265 if stages > 0 {
266 for stage in 0..(stages as usize) {
267 let idx = br.read(4)? as usize;
268 let src: &[i8] = match div {
269 BlockDiv::Div8x8 => &SVQ_INTER_CB_8X8[stage * 16 + idx],
270 BlockDiv::Div8x4 => &SVQ_INTER_CB_8X4[stage * 16 + idx],
271 BlockDiv::Div4x4 => &SVQ_INTER_CB_4X4[stage * 16 + idx],
272 BlockDiv::Div4x2 => &SVQ_INTER_CB_4X2[stage * 16 + idx],
273 _ => unreachable!(),
274 };
275 for (line, src) in dst[off..].chunks_mut(dstride).zip(src.chunks(w)) {
276 for x in 0..w {
277 line[x] = line[x].wrapping_add(src[x] as u8);
278 }
279 }
280 }
281 }
282 }
283 idx += 1;
284 }
285 Ok(())
286 }
287 fn decode_plane(&mut self, br: &mut BitReader, dframe: &mut NASimpleVideoFrame<u8>, plane: usize, is_intra: bool) -> DecoderResult<()> {
288 let (w, h) = if plane == 0 {
289 ((self.width + 15) & !15, (self.height + 15) & !15)
290 } else {
291 ((self.width / 4 + 15) & !15, (self.height / 4 + 15) & !15)
292 };
293 let mvstride = w / 8;
294 self.mvs.clear();
295 self.mvs.resize(mvstride * (h / 8), ZERO_MV);
296 let mut mv_idx = 0;
297
298 let mut doff = dframe.offset[plane];
299 let dstride = dframe.stride[plane];
300 for y in (0..h).step_by(16) {
301 for x in (0..w).step_by(16) {
302 let block_type = if is_intra {
303 BlockType::Intra
304 } else {
305 let idx = br.read_code(UintCodeType::LimitedZeroes(3))? as usize;
306 BLOCK_TYPES[idx]
307 };
308 match block_type {
309 BlockType::Intra => {
310 self.decode_intra_block(br, &mut dframe.data[doff + x..], dstride)?;
311 },
312 BlockType::Skip => {
313 if let Some(ref rfrm) = self.ref_frm {
314 let sstride = rfrm.get_stride(plane);
315 let soff = rfrm.get_offset(plane) + y * sstride;
316 let src = &rfrm.get_data()[soff + x..];
317 let dst = &mut dframe.data[doff + x..];
318 for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(16) {
319 dline[..16].copy_from_slice(&sline[..16]);
320 }
321 }
322 },
323 BlockType::OneMV => {
324 let mv = self.read_mv(br)?;
325 let new_mv = self.pred_mv(x, y, w, mv_idx + x / 8, mvstride, 0, mv);
326 self.mvs[mv_idx + x / 8] = new_mv;
327 self.mvs[mv_idx + x / 8 + 1] = new_mv;
328 self.mvs[mv_idx + mvstride + x / 8] = new_mv;
329 self.mvs[mv_idx + mvstride + x / 8 + 1] = new_mv;
330 if let Some(ref rfrm) = self.ref_frm {
331 let mode = ((new_mv.x & 1) + (new_mv.y & 1) * 2) as usize;
332 copy_block(dframe, rfrm.clone(), plane, x, y, new_mv.x >> 1, new_mv.y >> 1, 16, 16, 0, 1, mode, HALFPEL_INTERP_FUNCS);
333 }
334 self.decode_inter_block(br, &mut dframe.data[doff + x..], dstride)?;
335 },
336 BlockType::FourMV => {
337 for i in 0..4 {
338 let mv = self.read_mv(br)?;
339 let cur_idx = mv_idx + x / 8 + (i & 1) + (i >> 1) * mvstride;
340 let new_mv = self.pred_mv(x, y, w, cur_idx, mvstride, i, mv);
341 self.mvs[cur_idx] = new_mv;
342 if let Some(ref rfrm) = self.ref_frm {
343 let mode = ((new_mv.x & 1) + (new_mv.y & 1) * 2) as usize;
344 copy_block(dframe, rfrm.clone(), plane, x + (i & 1) * 8, y + (i >> 1) * 8, new_mv.x >> 1, new_mv.y >> 1, 8, 8, 0, 1, mode, HALFPEL_INTERP_FUNCS);
345 }
346 }
347 self.decode_inter_block(br, &mut dframe.data[doff + x..], dstride)?;
348 },
349 };
350 }
351 doff += dstride * 16;
352 mv_idx += mvstride * 2;
353 }
354 Ok(())
355 }
356}
357
358impl NADecoder for SVQ1Decoder {
359 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
360 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
361 self.width = vinfo.get_width();
362 self.height = vinfo.get_height();
363 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, YUV410_FORMAT));
364 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
365 supp.pool_u8.set_dec_bufs(2);
366 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, YUV410_FORMAT), 6)?;
367 self.mvs = Vec::with_capacity((self.width + 15) / 4 * ((self.height + 15) / 4));
368
369 Ok(())
370 } else {
371 Err(DecoderError::InvalidData)
372 }
373 }
374 #[allow(clippy::collapsible_if)]
375 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
376 let src = pkt.get_buffer();
377 validate!(src.len() >= 2);
378 let mut br = BitReader::new(&src, BitReaderMode::BE);
379
380 let fcode = br.read(22)?;
381 validate!((fcode & 0x60) != 0);
382 let _pts = br.read(8)?;
383 let ptype = br.read(2)?;
384 let ftype = SVQ1FrameType::from_id(ptype)?;
385 let mut frm_data = Vec::new();
386 if fcode != 0x20 {
387 frm_data.extend_from_slice(&src);
388 for i in 0..4 {
389 let a = frm_data[i * 4 + 4];
390 let b = frm_data[i * 4 + 5];
391 let c = frm_data[i * 4 + 6];
392 let d = frm_data[i * 4 + 7];
393 frm_data[i * 4 + 4] = c ^ frm_data[32 - i * 4];
394 frm_data[i * 4 + 5] = d ^ frm_data[33 - i * 4];
395 frm_data[i * 4 + 6] = a ^ frm_data[34 - i * 4];
396 frm_data[i * 4 + 7] = b ^ frm_data[35 - i * 4];
397 }
398 br = BitReader::new(&frm_data, BitReaderMode::BE);
399 br.skip(32)?;
400 }
401 if ftype.is_intra() {
402 if fcode == 0x50 || fcode == 0x60 {
403 let _checksum = br.read(16)? as u16;
404// let crc = calc_crc(frm_data.as_slice(), 0);
405// validate!(crc == _checksum);
406 }
407 if fcode == 0x40 || fcode == 0x60 || fcode == 0x70 {
408 let str_len = br.read(8)? as usize;
409 for _ in 0..str_len {
410 br.skip(8)?;
411 }
412 }
413 br.skip(2)?;
414 br.skip(2)?;
415 br.skip(1)?;
416 let size_id = br.read(3)? as usize;
417 let (w, h) = if size_id < FRAME_SIZES.len() {
418 FRAME_SIZES[size_id]
419 } else {
420 let w = br.read(12)? as usize;
421 let h = br.read(12)? as usize;
422 validate!(w >= 16 && h >= 16);
423 (w, h)
424 };
425 if self.width != w || self.height != h {
426 self.flush();
427 self.width = w;
428 self.height = h;
429 let vinfo = NAVideoInfo::new(self.width, self.height, false, YUV410_FORMAT);
430 supp.pool_u8.reset();
431 supp.pool_u8.prealloc_video(vinfo, 6)?;
432 let nmb = ((w + 15) / 4) * ((h + 15) / 4);
433 if self.mvs.capacity() < nmb {
434 let add = nmb - self.mvs.capacity();
435 self.mvs.reserve(add);
436 }
437 }
438 } else {
439 if self.ref_frm.is_none() {
440 return Err(DecoderError::MissingReference);
441 }
442 }
443 if br.read_bool()? {
444 let _pkt_crc = br.read_bool()?;
445 let _comp_crc = br.read_bool()?;
446 let marker = br.read(2)?;
447 validate!(marker == 0);
448 }
449 if br.read_bool()? {
450 br.skip(1)?;
451 br.skip(4)?;
452 br.skip(1)?;
453 br.skip(2)?;
454 while br.read_bool()? { }
455 }
456
457 let ret = supp.pool_u8.get_free();
458 if ret.is_none() {
459 return Err(DecoderError::AllocError);
460 }
461
462 let mut buf = ret.unwrap();
463 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
464 self.decode_plane(&mut br, &mut dframe, 0, ftype.is_intra())?;
465 self.decode_plane(&mut br, &mut dframe, 1, ftype.is_intra())?;
466 self.decode_plane(&mut br, &mut dframe, 2, ftype.is_intra())?;
467
468 if ftype.is_ref() {
469 self.ref_frm = Some(buf.clone());
470 }
471
472 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
473 frm.set_keyframe(ftype.is_intra());
474 frm.set_frame_type(ftype.to_frame_type());
475 Ok(frm.into_ref())
476 }
477 fn flush(&mut self) {
478 self.ref_frm = None;
479 }
480}
481
482impl NAOptionHandler for SVQ1Decoder {
483 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
484 fn set_options(&mut self, _options: &[NAOption]) { }
485 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
486}
487
488pub fn get_decoder() -> Box<dyn NADecoder + Send> {
489 Box::new(SVQ1Decoder::new())
490}
491
492
493#[cfg(test)]
494mod test {
495 use nihav_core::codecs::RegisteredDecoders;
496 use nihav_core::demuxers::RegisteredDemuxers;
497 use nihav_codec_support::test::dec_video::*;
498 use crate::qt_register_all_decoders;
499 use nihav_commonfmt::generic_register_all_demuxers;
500 #[test]
501 fn test_svq1() {
502 let mut dmx_reg = RegisteredDemuxers::new();
503 generic_register_all_demuxers(&mut dmx_reg);
504 let mut dec_reg = RegisteredDecoders::new();
505 qt_register_all_decoders(&mut dec_reg);
506
507 // sample: https://samples.mplayerhq.hu/A-codecs/ima-adpcm/adpcm-bug.mov
508 test_decoding("mov", "sorenson-video", "assets/QT/adpcm-bug.mov", Some(6), &dmx_reg, &dec_reg,
509 ExpectedTestResult::MD5Frames(vec![
510 [0x90c5eb74, 0xcb942d7d, 0x84c5e444, 0x7f1ba2c2],
511 [0x650ae6f7, 0x9a0a6ec2, 0x0d907064, 0xb4c37321],
512 [0xa04e865b, 0xdbd65920, 0x4703d7dd, 0x962707a1],
513 [0xe89c98bc, 0x356791bb, 0xfb6f7302, 0x2250ef05],
514 [0x282ef2a7, 0x235541b4, 0x55055d99, 0x1a8d0b29],
515 [0x79c60bab, 0xe5a11a50, 0x5f9e800b, 0x12bce70d],
516 [0xe9a08fb7, 0x3b482a8b, 0x50e1560e, 0xd6d70287]]));
517 }
518}
519
520const FRAME_SIZES: [(usize, usize); 7] = [
521 (160, 120), (128, 96), (176, 144), (352, 288),
522 (704, 576), (240, 180), (320, 240)
523];
524
525/*const CRC_TABLE: [u16; 256] = [ //CCITT 16-bit CRC?
526 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
527 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
528 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
529 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
530 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
531 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
532 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
533 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
534 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
535 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
536 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
537 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
538 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
539 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
540 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
541 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
542 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
543 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
544 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
545 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
546 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
547 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
548 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
549 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
550 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
551 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
552 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
553 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
554 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
555 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
556 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
557 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
558];
559
560fn calc_crc(src: &[u8], start: u16) -> u16 {
561 let mut crc = start;
562 for byte in src.iter() {
563 crc = CRC_TABLE[(*byte ^ ((crc >> 8) as u8)) as usize] ^ (crc << 8);
564 }
565 crc
566}*/