indeo5: fix off-by-one error in recombine_plane()
[nihav.git] / nihav-indeo / src / codecs / indeo5.rs
CommitLineData
5641dccf
KS
1use nihav_core::io::bitreader::*;
2use nihav_core::formats;
3use nihav_core::frame::*;
4use nihav_core::codecs::*;
b4d5b851 5use nihav_codec_support::codecs::ZIGZAG;
01c971c5
KS
6use super::ivi::*;
7use super::ivibr::*;
8
9fn calc_quant(glob_q: u32, qd: i16) -> usize {
10 let qq = (glob_q as i16) + (qd as i16);
11 if qq < 0 {
12 0
13 } else if qq > 23 {
14 23
15 } else {
16 qq as usize
17 }
18}
19
20struct Indeo5Parser {
21 mb_cb: IVICodebook,
22
23 width: usize,
24 height: usize,
25 tile_w: usize,
26 tile_h: usize,
27 luma_bands: usize,
28 chroma_bands: usize,
29
30 is_hpel: [bool; 5],
31 mb_size: [usize; 5],
32 blk_size: [usize; 5],
33}
34
35impl Indeo5Parser {
36 fn new() -> Self {
37 Indeo5Parser {
38 mb_cb: IVI_CB_ZERO,
39
40 width: 0,
41 height: 0,
42 tile_w: 0,
43 tile_h: 0,
44 luma_bands: 0,
45 chroma_bands: 0,
46
47 is_hpel: [false; 5],
48 mb_size: [0; 5],
49 blk_size: [0; 5],
50 }
51 }
52}
53
54fn skip_extension(br: &mut BitReader) -> DecoderResult<()> {
55 loop {
56 let len = br.read(8)?;
57 if len == 0 { break; }
58 br.skip(len * 8)?;
59 }
60 Ok(())
61}
62
63impl IndeoXParser for Indeo5Parser {
64#[allow(unused_variables)]
65#[allow(unused_assignments)]
66 fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> {
67 let sync = br.read(5)?;
68 validate!(sync == 0x1F);
69 let ftype_idx = br.read(3)?;
70 validate!(ftype_idx < 5);
71 let ftype = INDEO5_FRAME_TYPE[ftype_idx as usize];
72 let fnum = br.read(8)?;
73 if ftype == IVIFrameType::Intra {
74 let gop_flags = br.read(8)?;
75 let hdr_size;
76 if (gop_flags & 0x01) != 0 {
77 hdr_size = br.read(16)?;
78 } else {
79 hdr_size = 0;
80 }
81 if (gop_flags & 0x20) != 0 {
82 br.skip(32)?; // lock word
83 }
84 self.tile_w = 0;
85 self.tile_h = 0;
86 if (gop_flags & 0x40) != 0 {
87 self.tile_w = 64 << br.read(2)?;
88 self.tile_h = self.tile_w;
89 }
90 validate!(self.tile_w < 256);
91 self.luma_bands = (br.read(2)? * 3 + 1) as usize;
92 self.chroma_bands = (br.read(1)? * 3 + 1) as usize;
93 validate!((self.luma_bands == 4) || (self.luma_bands == 1));
94 validate!(self.chroma_bands == 1);
95 let pic_size_idx = br.read(4)? as usize;
96 let w;
97 let h;
98 if pic_size_idx < 15 {
99 w = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][0];
100 h = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][1];
101 } else {
102 h = br.read(13)? as usize;
103 w = br.read(13)? as usize;
104 }
105 validate!((w != 0) && (h != 0));
106 self.width = w;
107 self.height = h;
108
109 validate!((gop_flags & 0x02) == 0);
110 if self.tile_w == 0 {
111 self.tile_w = w;
112 self.tile_h = h;
113 }
114 for b in 0..self.luma_bands+self.chroma_bands {
115 self.is_hpel[b] = br.read_bool()?;
116 let mb_scale = br.read(1)?;
117 self.blk_size[b] = 8 >> br.read(1)?;
118 self.mb_size[b] = self.blk_size[b] << (1 - mb_scale);
119 let ext_tr = br.read_bool()?;
120 validate!(!ext_tr);
121 let end_marker = br.read(2)?;
122 validate!(end_marker == 0);
123 }
124 if (gop_flags & 0x08) != 0 {
125 let align = br.read(3)?;
126 validate!(align == 0);
127 if br.read_bool()? {
128 br.skip(24)?; // transparency color
129 }
130 }
131 br.align();
132 br.skip(23)?;
133 if br.read_bool()? { // gop extension
134 loop {
135 let v = br.read(16)?;
136 if (v & 0x8000) == 0 { break; }
137 }
138 }
139 br.align();
140 }
141 if ftype.is_null() {
142 br.align();
143 return Ok(PictureHeader::new_null(ftype));
144 }
145 let flags = br.read(8)?;
146 let size;
147 if (flags & 0x01) != 0 {
148 size = br.read(24)?;
149 } else {
150 size = 0;
151 }
152 let checksum;
153 if (flags & 0x10) != 0 {
154 checksum = br.read(16)?;
155 } else {
156 checksum = 0;
157 }
158 if (flags & 0x20) != 0 {
159 skip_extension(br)?;
160 }
161 let in_q = (flags & 0x08) != 0;
162 self.mb_cb = br.read_ivi_codebook_desc(true, (flags & 0x40) != 0)?;
163 br.skip(3)?;
164 br.align();
165
166 Ok(PictureHeader::new(ftype, self.width, self.height, self.tile_w, self.tile_h, false, self.luma_bands, self.chroma_bands, in_q))
167 }
168
169#[allow(unused_variables)]
170 fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane_no: usize, band_no: usize) -> DecoderResult<BandHeader> {
171 let band_flags = br.read(8)?;
172
173 if (band_flags & 0x01) != 0 {
174 br.align();
175 return Ok(BandHeader::new_empty(plane_no, band_no));
176 }
177 let inherit_mv = (band_flags & 0x02) != 0;
178 let has_qdelta = (band_flags & 0x04) != 0;
179 let inherit_qd = ((band_flags & 0x08) != 0) || !has_qdelta;
180 let data_size: usize;
181 if (band_flags & 0x80) != 0 {
182 data_size = br.read(24)? as usize;
51772ce8 183 validate!(data_size >= 4);
01c971c5
KS
184 } else {
185 data_size = 0;
186 }
51772ce8 187 validate!(data_size <= ((br.left() / 8) as usize) + 4);
01c971c5
KS
188
189 let num_corr: usize;
190 let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE];
191 if (band_flags & 0x10) != 0 {
192 num_corr = br.read(8)? as usize;
193 validate!(num_corr*2 <= CORR_MAP_SIZE);
194 for i in 0..num_corr*2 {
195 corr_map[i] = br.read(8)? as u8;
196 }
197 } else {
198 num_corr = 0;
199 }
200 let rvmap_idx;
201 if (band_flags & 0x40) != 0 {
202 rvmap_idx = br.read(3)? as usize;
203 } else {
204 rvmap_idx = 8;
205 }
206 let blk_cb = br.read_ivi_codebook_desc(false, (band_flags & 0x80) != 0)?;
207 if br.read_bool()? {
208 br.skip(16)?; // checksum
209 }
210 let band_q = br.read(5)?;
211 if (band_flags & 0x20) != 0 {
212 skip_extension(br)?;
213 }
214 br.align();
215
216 let tr;
217 let txtype;
218 let band_id = if plane_no == 0 { band_no } else { self.luma_bands };
219 match plane_no {
220 0 => {
221 let scan = INDEO5_SCAN8X8[band_no];
222 let qintra;
223 let qinter;
224 validate!(self.blk_size[band_id] == 8);
225 match band_no {
226 0 => {
227 tr = IVITransformType::Slant(TSize::T8x8, TDir::TwoD);
228 if self.luma_bands == 1 {
229 qintra = INDEO5_Q8_INTRA[0];
230 qinter = INDEO5_Q8_INTER[0];
231 } else {
232 qintra = INDEO5_Q8_INTRA[1];
233 qinter = INDEO5_Q8_INTER[1];
234 }
235 },
236 1 => {
237 tr = IVITransformType::Slant(TSize::T8x8, TDir::Row);
238 qintra = INDEO5_Q8_INTRA[2];
239 qinter = INDEO5_Q8_INTER[2];
240 },
241 2 => {
242 tr = IVITransformType::Slant(TSize::T8x8, TDir::Col);
243 qintra = INDEO5_Q8_INTRA[3];
244 qinter = INDEO5_Q8_INTER[3];
245 },
246 3 => {
247 tr = IVITransformType::None(TSize::T8x8);
248 qintra = INDEO5_Q8_INTRA[4];
249 qinter = INDEO5_Q8_INTER[4];
250 },
251 _ => { unreachable!(); }
252 };
253 txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan));
254 },
255 1 | 2 => {
256 validate!(self.blk_size[band_id] == 4);
257 tr = IVITransformType::Slant(TSize::T4x4, TDir::TwoD);
258 let scan = INDEO5_SCAN4X4;
259 let qintra = INDEO5_Q4_INTRA;
260 let qinter = INDEO5_Q4_INTER;
261 txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan));
262 },
263 _ => { unreachable!(); }
264 };
1a151e53 265
01c971c5
KS
266 Ok(BandHeader::new(plane_no, band_no, self.mb_size[band_id], self.blk_size[band_id], self.is_hpel[band_id], inherit_mv, has_qdelta, inherit_qd, band_q, rvmap_idx, num_corr, corr_map, blk_cb, tr, txtype))
267 }
268
b7c882c1 269 #[allow(clippy::cognitive_complexity)]
08a1fab7 270 fn decode_mb_info(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, band: &BandHeader, tile: &mut IVITile, ref_tile: Option<&IVITile>, mv_scale: u8) -> DecoderResult<()> {
01c971c5
KS
271 let mut mv_x = 0;
272 let mut mv_y = 0;
273 let band_id = if pic_hdr.luma_bands == 4 { band.band_no + 1 } else { 0 };
274 let mut mb_idx = 0;
275 for mb_y in 0..tile.mb_h {
276 for mb_x in 0..tile.mb_w {
277 let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
278 if !br.read_bool()? {
279 if pic_hdr.ftype.is_intra() {
280 mb.mtype = MBType::Intra;
281 } else if band.inherit_mv {
6f263099 282 if let Some(tileref) = ref_tile {
01c971c5
KS
283 mb.mtype = tileref.mb[mb_idx].mtype;
284 } else {
285 return Err(DecoderError::MissingReference);
286 }
287 } else {
288 mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
289 }
290 if band.mb_size == band.blk_size {
291 mb.cbp = br.read(1)? as u8;
292 } else {
293 mb.cbp = br.read(4)? as u8;
294 }
295 let q;
296 if band.has_qdelta {
297 if band.inherit_qd {
6f263099 298 if let Some(tileref) = ref_tile {
01c971c5
KS
299 mb.qd = tileref.mb[mb_idx].qd;
300 q = calc_quant(band.quant, mb.qd);
301 } else {
302 return Err(DecoderError::MissingReference);
303 }
304 } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
305 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
306 q = calc_quant(band.quant, mb.qd);
307 } else {
308 q = band.quant as usize;
309 }
310 } else {
311 q = band.quant as usize;
312 }
313
314 if mb.mtype == MBType::Intra {
315 if band.blk_size == 8 {
316 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
317 } else {
318 mb.q = INDEO5_QSCALE4_INTRA[q];
319 }
320 } else {
321 if band.blk_size == 8 {
322 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
323 } else {
324 mb.q = INDEO5_QSCALE4_INTER[q];
325 }
326 }
327
328 if mb.mtype != MBType::Intra {
329 if band.inherit_mv {
6f263099 330 if let Some(tileref) = ref_tile {
01c971c5
KS
331 let mx = tileref.mb[mb_idx].mv_x;
332 let my = tileref.mb[mb_idx].mv_y;
333 if mv_scale == 0 {
334 mb.mv_x = mx;
335 mb.mv_y = my;
336 } else {
337 mb.mv_x = scale_mv(mx, mv_scale);
338 mb.mv_y = scale_mv(my, mv_scale);
339 }
340 }
341 } else {
342 mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
343 mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
344 mb.mv_x = mv_x;
345 mb.mv_y = mv_y;
346 }
347 }
348 } else {
349 validate!(!pic_hdr.ftype.is_intra());
350 mb.mtype = MBType::Inter;
351 mb.cbp = 0;
352 mb.qd = 0;
353 if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
354 mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
355 let q = calc_quant(band.quant, mb.qd);
356 if mb.mtype == MBType::Intra {
357 if band.blk_size == 8 {
358 mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
359 } else {
360 mb.q = INDEO5_QSCALE4_INTRA[q];
361 }
362 } else {
363 if band.blk_size == 8 {
364 mb.q = INDEO5_QSCALE8_INTER[band_id][q];
365 } else {
366 mb.q = INDEO5_QSCALE4_INTER[q];
367 }
368 }
369 }
370 if band.inherit_mv {
6f263099 371 if let Some(tileref) = ref_tile {
01c971c5
KS
372 let mx = tileref.mb[mb_idx].mv_x;
373 let my = tileref.mb[mb_idx].mv_y;
374 if mv_scale == 0 {
375 mb.mv_x = mx;
376 mb.mv_y = my;
377 } else {
378 mb.mv_x = scale_mv(mx, mv_scale);
379 mb.mv_y = scale_mv(my, mv_scale);
380 }
381 }
382 }
383 }
384 tile.mb[mb_idx] = mb;
385 mb_idx += 1;
386 }
387 }
388 br.align();
389 Ok(())
390 }
391
392 fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
393 let mut idx0 = 0;
394 let mut idx1 = w / 2;
395 let mut idx2 = (h / 2) * sstride;
396 let mut idx3 = idx2 + idx1;
397 let mut bidx1 = idx1;
398 let mut bidx3 = idx3;
399 let mut oidx0 = 0;
400 let mut oidx1 = dstride;
401 let filt_lo = |a: i16, b: i16| a + b;
402 let filt_hi = |a: i16, b: i16, c: i16| a - b * 6 + c;
403
6048a37f 404 for _ in 0..(h/2)-1 {
01c971c5
KS
405 let mut b0_1 = src[idx0];
406 let mut b0_2 = src[idx0 + sstride];
407 let mut b1_1 = src[bidx1];
408 let mut b1_2 = src[idx1];
409 let mut b1_3 = filt_hi(b1_1, b1_2, src[idx1 + sstride]);
410 let mut b2_1;
411 let mut b2_2 = src[idx2];
412 let mut b2_3 = b2_2;
413 let mut b2_4;
414 let mut b2_5 = src[idx2 + sstride];
415 let mut b2_6 = b2_5;
416 let mut b3_1;
417 let mut b3_2 = src[bidx3];
418 let mut b3_3 = b3_2;
419 let mut b3_4;
420 let mut b3_5 = src[idx3];
421 let mut b3_6 = b3_5;
422 let mut b3_8 = filt_hi(b3_2, b3_5, src[idx3 + sstride]);
423 let mut b3_9 = b3_8;
424 let mut b3_7;
425
6048a37f 426 for x in 0..(w/2)-1 {
01c971c5
KS
427 b2_1 = b2_2;
428 b2_2 = b2_3;
429 b2_4 = b2_5;
430 b2_5 = b2_6;
431 b3_1 = b3_2;
432 b3_2 = b3_3;
433 b3_4 = b3_5;
434 b3_5 = b3_6;
435 b3_7 = b3_8;
436 b3_8 = b3_9;
437
438 let tmp0 = b0_1;
439 let tmp1 = b0_2;
440 b0_1 = src[idx0 + x + 1];
441 b0_2 = src[idx0 + x + 1 + sstride];
442 let mut p0 = tmp0 << 4;
443 let mut p1 = (tmp0 + b0_1) << 3;
444 let mut p2 = (tmp0 + tmp1) << 3;
445 let mut p3 = (tmp0 + tmp1 + b0_1 + b0_2) << 2;
446
447 let tmp0 = b1_1;
448 let tmp1 = b1_2;
449 let tmp2 = filt_lo(tmp0, tmp1);
450 let tmp3 = filt_hi(tmp0, tmp1, b1_3);
451 b1_2 = src[ idx1 + x + 1];
452 b1_1 = src[bidx1 + x + 1];
453 b1_3 = filt_hi(b1_1, b1_2, src[idx1 + x + 1 + sstride]);
454 p0 += tmp2 << 3;
455 p1 += (tmp2 + b1_1 + b1_2) << 2;
456 p2 += tmp3 << 2;
457 p3 += (tmp3 + b1_3) << 1;
458
459 b2_3 = src[idx2 + x + 1];
460 b2_6 = src[idx2 + x + 1 + sstride];
461 let tmp0 = filt_lo(b2_1, b2_2);
462 let tmp1 = filt_hi(b2_1, b2_2, b2_3);
463 p0 += tmp0 << 3;
464 p1 += tmp1 << 2;
465 p2 += (tmp0 + filt_lo(b2_4, b2_5)) << 2;
466 p3 += (tmp1 + filt_hi(b2_4, b2_5, b2_6)) << 1;
467
468 b3_6 = src[idx3 + x + 1];
469 b3_3 = src[bidx3 + x + 1];
470 b3_9 = filt_hi(b3_3, b3_6, src[idx3 + x + 1 + sstride]);
471 let tmp0 = b3_1 + b3_4;
472 let tmp1 = b3_2 + b3_5;
473 let tmp2 = b3_3 + b3_6;
474 p0 += filt_lo(tmp0, tmp1) << 2;
475 p1 += filt_hi(tmp0, tmp1, tmp2) << 1;
476 p2 += filt_lo(b3_7, b3_8) << 1;
477 p3 += filt_hi(b3_7, b3_8, b3_9) << 0;
478
479 dst[oidx0 + x * 2 + 0] = clip8((p0 >> 6) + 128);
480 dst[oidx0 + x * 2 + 1] = clip8((p1 >> 6) + 128);
481 dst[oidx1 + x * 2 + 0] = clip8((p2 >> 6) + 128);
482 dst[oidx1 + x * 2 + 1] = clip8((p3 >> 6) + 128);
483 }
484 bidx1 = idx1;
485 bidx3 = idx3;
486 idx0 += sstride;
487 idx1 += sstride;
488 idx2 += sstride;
489 idx3 += sstride;
490 oidx0 += dstride * 2;
491 oidx1 += dstride * 2;
492 }
493 }
494}
495
496struct Indeo5Decoder {
2422d969 497 info: NACodecInfoRef,
01c971c5
KS
498 dec: IVIDecoder,
499 ip: Indeo5Parser,
500}
501
502impl Indeo5Decoder {
f7686373 503 fn new(scalable: bool) -> Self {
01c971c5
KS
504 Indeo5Decoder {
505 info: NACodecInfo::new_dummy(),
f7686373 506 dec: IVIDecoder::new(scalable),
01c971c5
KS
507 ip: Indeo5Parser::new(),
508 }
509 }
510}
511
512impl NADecoder for Indeo5Decoder {
01613464 513 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
01c971c5
KS
514 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
515 let w = vinfo.get_width();
516 let h = vinfo.get_height();
517 let f = vinfo.is_flipped();
518 let fmt = formats::YUV410_FORMAT;
519 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
2422d969 520 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
01c971c5
KS
521 Ok(())
522 } else {
523 Err(DecoderError::InvalidData)
524 }
525 }
01613464 526 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
01c971c5 527 let src = pkt.get_buffer();
fa90ccfb 528 let mut br = BitReader::new(src.as_slice(), BitReaderMode::LE);
01c971c5
KS
529
530 let bufinfo = self.dec.decode_frame(&mut self.ip, &mut br)?;
531 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
532 frm.set_keyframe(self.dec.is_intra());
533 frm.set_frame_type(self.dec.get_frame_type());
171860fc 534 Ok(frm.into_ref())
01c971c5 535 }
f9be4e75
KS
536 fn flush(&mut self) {
537 self.dec.flush();
538 }
01c971c5
KS
539}
540
7d57ae2f
KS
541impl NAOptionHandler for Indeo5Decoder {
542 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
543 fn set_options(&mut self, _options: &[NAOption]) { }
544 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
545}
546
01c971c5
KS
547const INDEO5_PICTURE_SIZE_TAB: [[usize; 2]; 15] = [
548 [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144],
549 [240, 180], [640, 240], [704, 240], [80, 60], [88, 72], [0, 0], [0, 0], [0, 0]
550];
551
552const INDEO5_FRAME_TYPE: [IVIFrameType; 5] = [
553 IVIFrameType::Intra, IVIFrameType::Inter, IVIFrameType::InterScal,
554 IVIFrameType::InterDroppable, IVIFrameType::NULL,
555];
556
557const INDEO5_QUANT8X8_INTRA: [[u16; 64]; 5] = [
558 [
559 0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a,
560 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a,
561 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72,
562 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a,
563 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e,
564 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6,
565 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca,
566 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe,
567 ], [
568 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
569 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
570 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
571 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
572 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
573 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
574 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
575 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
576 ], [
577 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
578 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
579 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
580 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
581 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
582 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
583 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
584 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
585 ], [
586 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
587 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
588 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
589 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
590 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
591 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
592 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
593 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
594 ], [
595 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
596 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
597 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
598 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
599 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
600 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
601 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
602 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
603 ]
604];
605const INDEO5_QUANT8X8_INTER: [[u16; 64]; 5] = [
606 [
607 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
608 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
609 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
610 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
611 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
612 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
613 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
614 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
615 ], [
616 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
617 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
618 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
619 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
620 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
621 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
622 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
623 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
624 ], [
625 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
626 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
627 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
628 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
629 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
630 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
631 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
632 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
633 ], [
634 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
635 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
636 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
637 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
638 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
639 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
640 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
641 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
642 ], [
643 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
644 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
645 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
646 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
647 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
648 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
649 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
650 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
651 ]
652];
653const INDEO5_QUANT4X4_INTRA: [u16; 16] = [
654 0x1e, 0x3e, 0x4a, 0x52,
655 0x3e, 0x4a, 0x52, 0x5e,
656 0x4a, 0x52, 0x5e, 0x7a,
657 0x52, 0x5e, 0x7a, 0x92
658];
659const INDEO5_QUANT4X4_INTER: [u16; 16] = [
660 0x1e, 0x3e, 0x4a, 0x52,
661 0x3e, 0x4a, 0x52, 0x56,
662 0x4a, 0x52, 0x56, 0x5e,
663 0x52, 0x56, 0x5e, 0x66
664];
665const INDEO5_Q8_INTRA: [&[u16; 64]; 5] = [
666 &INDEO5_QUANT8X8_INTRA[0], &INDEO5_QUANT8X8_INTRA[1], &INDEO5_QUANT8X8_INTRA[2],
667 &INDEO5_QUANT8X8_INTRA[3], &INDEO5_QUANT8X8_INTRA[4],
668];
669const INDEO5_Q8_INTER: [&[u16; 64]; 5] = [
670 &INDEO5_QUANT8X8_INTER[0], &INDEO5_QUANT8X8_INTER[1], &INDEO5_QUANT8X8_INTER[2],
671 &INDEO5_QUANT8X8_INTER[3], &INDEO5_QUANT8X8_INTER[4],
672];
673const INDEO5_Q4_INTRA: &[u16; 16] = &INDEO5_QUANT4X4_INTRA;
674const INDEO5_Q4_INTER: &[u16; 16] = &INDEO5_QUANT4X4_INTER;
675
676const INDEO5_SCAN8X8: [&[usize; 64]; 4] = [
64e8b971 677 &ZIGZAG, &IVI_SCAN_8X8_VER, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_HOR
01c971c5
KS
678];
679const INDEO5_SCAN4X4: &[usize; 16] = &IVI_SCAN_4X4;
680
681const INDEO5_QSCALE8_INTRA: [[u8; 24]; 5] = [
682 [
683 0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
684 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c,
685 ], [
686 0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c,
687 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c,
688 ], [
689 0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e,
690 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95,
691 ], [
692 0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d,
693 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b,
694 ], [
695 0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b,
696 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4,
697 ]
698];
699const INDEO5_QSCALE8_INTER: [[u8; 24]; 5] = [
700 [
701 0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22,
702 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a,
703 ], [
704 0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35,
705 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e,
706 ], [
707 0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51,
708 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97,
709 ], [
710 0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39,
711 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62,
712 ], [
713 0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80,
714 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba
715 ]
716];
717const INDEO5_QSCALE4_INTRA: [u8; 24] = [
718 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14,
719 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
720];
721const INDEO5_QSCALE4_INTER: [u8; 24] = [
722 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
723 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
724];
725
08a1fab7 726pub fn get_decoder() -> Box<dyn NADecoder + Send> {
f7686373
KS
727 Box::new(Indeo5Decoder::new(false))
728}
729
730pub fn get_decoder_scalable() -> Box<dyn NADecoder + Send> {
731 Box::new(Indeo5Decoder::new(true))
01c971c5
KS
732}
733
734#[cfg(test)]
735mod test {
3167c45c
KS
736 use nihav_core::codecs::RegisteredDecoders;
737 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 738 use nihav_codec_support::test::dec_video::*;
78fb6560 739 use crate::indeo_register_all_decoders;
e64739f8 740 use nihav_commonfmt::generic_register_all_demuxers;
01c971c5
KS
741 #[test]
742 fn test_indeo5() {
3167c45c
KS
743 let mut dmx_reg = RegisteredDemuxers::new();
744 generic_register_all_demuxers(&mut dmx_reg);
745 let mut dec_reg = RegisteredDecoders::new();
78fb6560 746 indeo_register_all_decoders(&mut dec_reg);
3167c45c 747
886cde48 748 // sample: https://samples.mplayerhq.hu/V-codecs/IV50/sample.avi
122c047f
KS
749 test_decoding("avi", "indeo5", "assets/Indeo/IV5/sample.avi", Some(100),
750 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
6048a37f
KS
751 [0xcb451428, 0x5c8b1519, 0x96a81eda, 0x0c9cccf0],
752 [0x7554e11f, 0x3b60d661, 0x3bcd14b5, 0x036dcc16],
753 [0x92a20e68, 0x83418e5c, 0x640b6786, 0x9c867622],
754 [0x0b2cde46, 0x67b68ac5, 0xc152edc6, 0xda591ac3],
755 [0x9034354b, 0x81c66b57, 0xcb671505, 0x0062a75f],
756 [0x38606276, 0x547b83df, 0x4a22f079, 0x2afb8362],
757 [0x0d3fe5df, 0xadc8b042, 0x4ee9cb0d, 0xf9b79b11],
758 [0x2b0b1ddb, 0x612a163a, 0x47b5afc8, 0xeb4c79a5],
759 [0x8eadd17e, 0xc4c8c932, 0x57508232, 0x643e1498],
760 [0x0dcc7da2, 0x7b059de2, 0x0ff46dd9, 0x04c11f77],
761 [0xe358728a, 0xe42fc515, 0x8f5cc35f, 0x02973436],
762 [0x66847a32, 0x884b41f0, 0x0c3062bc, 0xb58d923b],
763 [0x555b2711, 0xbcb54b64, 0x5a6141e5, 0xa7b5cc44],
764 [0x0f326348, 0x5d36cb21, 0xe7f8210d, 0x8a43c2c5],
765 [0x4e7b18a3, 0x42146bbb, 0x04c4cf2b, 0x78fe3c0d],
766 [0x220f0721, 0xe681444a, 0x974bf97b, 0x9b658cfe],
767 [0x2d5a5f22, 0x23bd1ed8, 0xed383633, 0x5905422d],
768 [0x982ae872, 0x17b8f765, 0x3d1735af, 0xa2872d9f],
769 [0x743a2819, 0x392d856e, 0xf2ee64ca, 0x63101b79],
770 [0x0c9e0aa7, 0x79414f6b, 0x162c19a6, 0x86d69b96],
771 [0x3eae05ad, 0xbff350bb, 0x97e8a205, 0xfa8e42b2],
772 [0x0ccae893, 0xdfcf9885, 0xef39d053, 0x0a655a73],
773 [0x75e98d11, 0x83fab601, 0xe836a6d2, 0xb2a7c7cb],
774 [0x1565b1ce, 0x8ab813c5, 0xb1658413, 0xeebaf068],
775 [0xe2bb47dd, 0xc3c277a7, 0x8c6bd4be, 0xbbca989d],
776 [0xea97912e, 0xcd224d66, 0x76fd31c2, 0x7a854abf],
777 [0x8eebb842, 0x0534b043, 0xf55a3b65, 0x3868b974],
778 [0x82c55a0b, 0x5d18c3c8, 0xbdc40fd1, 0x5d11f2e2],
779 [0xda46bff0, 0xedc1e115, 0x77cb8b8a, 0xf5fd6ddf],
780 [0x7c9c19e9, 0x4188e742, 0xd8c2cbaf, 0x0ecd1aaa],
781 [0x33145d5b, 0x0c8e2f61, 0x2ab4b213, 0xf1cf9ebe],
782 [0x64f561e1, 0xae2aa75b, 0xe4d56a57, 0xdcc54d10],
783 [0x25545f02, 0x8c271a6a, 0x6b676110, 0xa348628b],
784 [0x8c33d2d7, 0x7dfc25a0, 0xbdb68979, 0xac7ce8f1],
785 [0x8adc7126, 0x71c4d390, 0x4b47aeed, 0x444dbd2b],
786 [0xaab41fbc, 0x2c6de4d8, 0x83b61f31, 0xc68879b1],
787 [0x90961b3a, 0x9a1d4b51, 0xbf34d9d1, 0xe90137a7],
788 [0x2e988439, 0x2d7e67ec, 0x9bfd6405, 0xd851ee32],
789 [0x3b2b45e8, 0x76225018, 0xa2632614, 0x06234ca9],
790 [0xd52dc6af, 0x36c0d185, 0x90f4a9d2, 0x0b024990],
791 [0x5ed3ebb2, 0xb19b49a2, 0xd691c27a, 0x7d52941c],
792 [0xcb22479a, 0x3713b23d, 0x24abe31b, 0x45877b4e],
793 [0x143aa9f1, 0xe7709011, 0xa6ef993b, 0x8e4f33e2],
794 [0xc8b1ad16, 0x820b4f85, 0xe9d1482a, 0x806af90c],
795 [0x4f1eda2b, 0xa73eac8c, 0x8004e66b, 0xa0804e11],
796 [0x668ceb7b, 0xad020ed3, 0x90687534, 0x96eded7e],
797 [0x8bbd77d0, 0x29fc1ae4, 0xc41fb7cf, 0x31b08f08],
798 [0x02d07857, 0x4ed79f55, 0x89cfe082, 0x97167616],
799 [0xd99dbf57, 0x87ef7406, 0x59c9abdf, 0xf664be32],
800 [0x6d2bd834, 0x6b61d6e5, 0x3fd282ce, 0xbc877248],
801 [0xb4dbab3f, 0x7006dded, 0x39608927, 0x9773b83e],
802 [0x6e1f21e8, 0xff1a76c0, 0x197dd40b, 0x3cedee3d],
803 [0x551f64b8, 0x98161c0f, 0xb93103a7, 0xac12366e],
804 [0x6854311c, 0x6bc09f24, 0x226ec3e9, 0x91507815],
805 [0xb106d988, 0x6c9cda70, 0xebf972ce, 0x97b1efa8],
806 [0x91b8c27b, 0x257ff731, 0x1589d60d, 0xcb2b3de9],
807 [0x819d3677, 0xa6afca81, 0x3d2b4ba9, 0xba8cc70f],
808 [0xfb2c67fa, 0x75af7785, 0xde6133b0, 0x1bb59f2c],
809 [0xceb72cd4, 0x8c581ccb, 0x803233f2, 0xb88a174b],
810 [0xe2811f64, 0xa488d42c, 0x3a62a574, 0x918df881],
811 [0x95a66cf8, 0x0529a646, 0x3bc15b00, 0xfb0eedc9],
812 [0x1e90f3ce, 0xa8f81b7f, 0x13d5445c, 0xc969a914],
813 [0x25287783, 0x19869a3d, 0x93672c2a, 0x07a57f5e],
814 [0x44dfacc0, 0x528ae192, 0x141721a9, 0x85b2a3d9],
815 [0x45f13c20, 0x90b07bb5, 0x9a155a2f, 0x3933fb77],
816 [0x40531c62, 0x437c14b6, 0xc03c8d39, 0x35f5ae87],
817 [0x32e58909, 0xdb068147, 0xa967c6cf, 0x33d9416a],
818 [0xa8c44523, 0x12a89332, 0xddd09ccf, 0x7b04c0d2],
819 [0xae00b8b4, 0x589efb18, 0xf8c1dec1, 0xfd9d867f],
820 [0xe2fc1828, 0x5f7a3b28, 0x72de1c32, 0xc01e6ea6],
821 [0x8be4c525, 0xcde70d98, 0xd7f5f5a1, 0xf39faadf],
822 [0x9c744944, 0x00a491f4, 0x665707a9, 0xa93fad9d],
823 [0x036f2525, 0x827ddd36, 0x989c99db, 0x6b9455fc],
824 [0x52c6b5d2, 0xfd4e23f9, 0xb620b0da, 0x462d7566],
825 [0x00ba54e6, 0xfe9021ae, 0xa8c65c37, 0xda979c78],
826 [0x6e11dca0, 0x41887539, 0x2b9781af, 0x94e6b930],
827 [0x086be7db, 0xcce50438, 0x2d94bc75, 0x00f4ebfe],
828 [0xd2216f7c, 0x33321d48, 0x8ce0f144, 0x34c1fd4f],
829 [0x9083c0fc, 0x6cb46451, 0xd8202b2f, 0xae5db326],
830 [0xe894be71, 0x0e1b6c67, 0x70d5e81f, 0x2075d5ff],
831 [0x7f9f10f7, 0x0a8df81d, 0x406cb9cc, 0x524879b5],
832 [0x4c329904, 0x6f939b2c, 0xd49f8bba, 0xad54aee5],
833 [0x92d68b43, 0x2c631f71, 0x98329455, 0x91971f7f],
834 [0x1b06289e, 0x4879af78, 0xc66d7c82, 0xda19e863],
835 [0x399741da, 0xd362b007, 0x8f94e50c, 0xcdd23209],
836 [0xa2063194, 0xc67f368a, 0x83462433, 0xe719c2db],
837 [0x9da0bfd1, 0x8977f90e, 0x7f2f4172, 0xab5213ff],
838 [0x82823c8f, 0xd7cdd62e, 0xac3a59ba, 0x17ef0fb9],
839 [0xb3e51375, 0xfebb3ad3, 0x54ffdda4, 0xfbf44cf9],
840 [0x261f8183, 0x8328012b, 0x47d7e527, 0xc19cca15],
841 [0xef25bfc7, 0x79460e21, 0xeb65f2ef, 0x63731f9f],
842 [0xd14fc8f5, 0x209123ea, 0xf5f1cf21, 0x93f84381],
843 [0xf5375f67, 0x0846d9a1, 0x07aaf802, 0xe753fa08],
844 [0x65a56edd, 0x4ea28e39, 0x10d17a7b, 0xa9445d87],
845 [0xbeb8eb53, 0xd01b9c94, 0xd1d15e41, 0x639307cc],
846 [0xc2272546, 0xd1701452, 0x2fe76cbd, 0xe1dd7697],
847 [0xff6c09f6, 0x1d7804c2, 0x1ca3a2f8, 0x3fffb67b],
848 [0xfe48f3fd, 0x0046ec25, 0x1ed4401a, 0xd67f4ed6],
849 [0x46c3c72f, 0x8398b8c1, 0xe26aff08, 0x0dd1ecbb],
850 [0xc7f49f94, 0xca32d87c, 0x2e063788, 0x0229c6c0],
851 [0xa9ec4820, 0x576c7877, 0xc21211c3, 0x502af3d3]]));
01c971c5
KS
852 }
853}