rename register_all_codecs to register_all_decoders
[nihav.git] / nihav-qt / src / codecs / svq1.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::bitreader::*;
3 use nihav_core::io::codebook::*;
4 use nihav_core::io::intcode::*;
5 use nihav_codec_support::codecs::{MV, ZERO_MV};
6 use nihav_codec_support::codecs::blockdsp::*;
7
8 use super::svq1data::*;
9
10 #[derive(Clone,Copy,Debug,PartialEq)]
11 enum SVQ1FrameType {
12 I,
13 P,
14 Drop,
15 }
16
17 #[derive(Clone,Copy,Debug,PartialEq)]
18 enum BlockType {
19 Intra,
20 Skip,
21 OneMV,
22 FourMV,
23 }
24
25 #[derive(Clone,Copy,Debug,PartialEq)]
26 #[allow(clippy::enum_variant_names)]
27 enum BlockDiv {
28 Div16x16,
29 Div16x8,
30 Div8x8,
31 Div8x4,
32 Div4x4,
33 Div4x2,
34 }
35
36 impl 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
70 const BLOCK_TYPES: [BlockType; 4] = [ BlockType::Skip, BlockType::OneMV, BlockType::FourMV, BlockType::Intra ];
71
72 impl 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
96 struct SVQ1DescReader {
97 table: &'static [[u8; 2]],
98 bias: i16,
99 }
100
101 impl 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
108 struct SVQ1InterMeanDescReader {}
109
110 impl 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
117 struct 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
132 impl 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 = (i16::from(*el) + fill).max(0).min(255) 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] = (i16::from(line[x]) + i16::from(src[x])).max(0).min(255) 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.truncate(0);
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
358 impl 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
482 impl 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
488 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
489 Box::new(SVQ1Decoder::new())
490 }
491
492
493 #[cfg(test)]
494 mod 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 test_decoding("mov", "sorenson-video", "assets/QT/adpcm-bug.mov", Some(6), &dmx_reg, &dec_reg,
508 ExpectedTestResult::MD5Frames(vec![
509 [0x90c5eb74, 0xcb942d7d, 0x84c5e444, 0x7f1ba2c2],
510 [0x650ae6f7, 0x9a0a6ec2, 0x0d907064, 0xb4c37321],
511 [0xa04e865b, 0xdbd65920, 0x4703d7dd, 0x962707a1],
512 [0xe89c98bc, 0x356791bb, 0xfb6f7302, 0x2250ef05],
513 [0x282ef2a7, 0x235541b4, 0x55055d99, 0x1a8d0b29],
514 [0x56328694, 0x27157f78, 0x4bc6ddda, 0x03dcde68],
515 [0x5a694576, 0xd2434aea, 0x6859d48c, 0x275e02c9]]));
516 }
517 }
518
519 const FRAME_SIZES: [(usize, usize); 7] = [
520 (160, 120), (128, 96), (176, 144), (352, 288),
521 (704, 576), (240, 180), (320, 240)
522 ];
523
524 /*const CRC_TABLE: [u16; 256] = [ //CCITT 16-bit CRC?
525 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
526 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
527 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
528 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
529 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
530 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
531 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
532 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
533 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
534 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
535 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
536 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
537 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
538 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
539 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
540 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
541 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
542 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
543 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
544 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
545 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
546 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
547 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
548 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
549 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
550 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
551 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
552 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
553 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
554 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
555 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
556 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
557 ];
558
559 fn calc_crc(src: &[u8], start: u16) -> u16 {
560 let mut crc = start;
561 for byte in src.iter() {
562 crc = CRC_TABLE[(*byte ^ ((crc >> 8) as u8)) as usize] ^ (crc << 8);
563 }
564 crc
565 }*/