--- /dev/null
+use std::cell::Ref;
+use io::bitreader::*;
+use formats;
+use super::super::*;
+use super::ivi::*;
+use super::ivibr::*;
+
+struct Indeo4Parser {
+ mb_cb: IVICodebook,
+ blk_cb: IVICodebook,
+}
+
+fn calc_quant(glob_q: u32, qd: i16) -> u8 {
+ let q = (glob_q as i16) + qd;
+ if q < 0 {
+ 0
+ } else if q > 31 {
+ 31
+ } else {
+ q as u8
+ }
+}
+
+impl Indeo4Parser {
+ fn new() -> Self {
+ Indeo4Parser {
+ mb_cb: IVI_CB_ZERO,
+ blk_cb: IVI_CB_ZERO,
+ }
+ }
+}
+
+impl IndeoXParser for Indeo4Parser {
+#[allow(unused_variables,unused_assignments)]
+ fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> {
+ let sync = br.read(18)?;
+ validate!(sync == 0x3FFF8);
+ let ftype_idx = br.read(3)?;
+ validate!(ftype_idx < 7);
+ let ftype = INDEO4_FRAME_TYPE[ftype_idx as usize];
+ let transparent = br.read_bool()?;
+ br.skip(1)?;
+ let data_size;
+ if br.read_bool()? {
+ data_size = br.read(24)? as usize;
+ } else {
+ data_size = 0;
+ }
+ if ftype.is_null() {
+ return Ok(PictureHeader::new_null(ftype));
+ }
+ if br.read_bool()? {
+ br.skip(32)?; // key lock
+ }
+ let width;
+ let height;
+ let pic_size_idx = br.read(3)?;
+ if pic_size_idx < 7 {
+ width = INDEO4_PICTURE_SIZE_TAB[pic_size_idx as usize][0];
+ height = INDEO4_PICTURE_SIZE_TAB[pic_size_idx as usize][1];
+ } else {
+ height = br.read(16)? as usize;
+ width = br.read(16)? as usize;
+ validate!((width > 0) && ((width & 3) == 0));
+ validate!((height > 0) && ((height & 3) == 0));
+ }
+
+ let slice_w;
+ let slice_h;
+ if br.read_bool()? {
+ let idx = br.read(4)? as usize;
+ if idx < 15 {
+ slice_w = INDEO4_SLICE_SIZE_TAB[idx];
+ slice_h = INDEO4_SLICE_SIZE_TAB[idx];
+ } else {
+ slice_w = width;
+ slice_h = height;
+ }
+ } else {
+ slice_w = width;
+ slice_h = height;
+ }
+ let subsampling = br.read(2)?;
+ validate!(subsampling == 0);
+ let sc_idx = br.read(2)?;
+ match sc_idx {
+ 3 => { },
+ 2 => { validate!(br.read(2*4)? == 0xFF); }
+ _ => { return Err(DecoderError::InvalidData); }
+ };
+ let luma_bands = if sc_idx == 2 { 4 } else { 1 };
+ let sc_idx = br.read(2)?;
+ match sc_idx {
+ 3 => { },
+ 2 => { validate!(br.read(2*4)? == 0xFF); }
+ _ => { return Err(DecoderError::InvalidData); }
+ };
+ let chroma_bands = if sc_idx == 2 { 4 } else { 1 };
+ let frame_no;
+ if br.read_bool()? {
+ frame_no = br.read(20)?;
+ } else {
+ frame_no = 0;
+ }
+ if br.read_bool()? {
+ br.skip(8)?; // decTimeEst
+ }
+ let desc_coded = br.read_bool()?;
+ self.mb_cb = br.read_ivi_codebook_desc(true, desc_coded)?;
+ let desc_coded = br.read_bool()?;
+ self.blk_cb = br.read_ivi_codebook_desc(false, desc_coded)?;
+ let rvmap = if br.read_bool()? { br.read(3)? as usize } else { 8 };
+ let in_imf = br.read_bool()?;
+ let in_q = br.read_bool()?;
+ let glob_q = br.read(5)? as u8;
+ if br.read_bool()? {
+ br.skip(3)?;
+ }
+ let checksum = if br.read_bool()? { br.read(16)? } else { 0 };
+ if br.read_bool()? {
+ br.skip(8)?; // pic hdr extension
+ }
+ if br.read_bool()? {
+ println!("bad blocks bits!");
+ }
+ br.align();
+
+ Ok(PictureHeader::new(ftype, width, height, slice_w, slice_h, transparent, luma_bands, chroma_bands, in_q))
+ }
+
+#[allow(unused_variables,unused_assignments)]
+ fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane: usize, band: usize) -> DecoderResult<BandHeader> {
+ let plane_no = br.read(2)? as usize;
+ let band_no = br.read(4)? as usize;
+ validate!(plane_no == plane);
+ validate!(band_no == band);
+ if br.read_bool()? {
+ br.align();
+ return Ok(BandHeader::new_empty(plane_no, band_no));
+ }
+ let hdr_size;
+ if br.read_bool()? {
+ hdr_size = br.read(16)? as usize;
+ } else {
+ hdr_size = 32;
+ }
+ let mv_mode = br.read(2)?;
+ validate!(mv_mode < 2);
+ if br.read_bool()? {
+ br.skip(16)?; //checksum
+ }
+
+ let scale = br.read(2)?;
+ validate!(scale != 3);
+ let mb_size = 16 >> scale;
+ let blk_size = 8 >> (scale >> 1);
+ let inherit_mv = br.read_bool()?;
+ let inherit_qd = br.read_bool()?;
+ let quant = br.read(5)?;
+
+ let tr: IVITransformType;
+ let txtype: TxType;
+ if !br.read_bool()? || pic_hdr.ftype == IVIFrameType::Intra {
+ let tr_id = br.read(5)?;
+ validate!(tr_id < 18);
+ let scan_idx = br.read(4)? as usize;
+ validate!(scan_idx != 15);
+ let qmat_idx = br.read(5)? as usize;
+
+ tr = INDEO4_TRANSFORMS[tr_id as usize];
+ if (scan_idx < 5) || (scan_idx >= 10) {
+ validate!(tr.is_8x8());
+ validate!(qmat_idx < 15);
+ let scan = if scan_idx < 5 { INDEO4_SCANS_8X8[scan_idx] }
+ else { INDEO4_SCANS_8X8[4] };
+ let qidx = INDEO4_Q8X8_IDX[qmat_idx];
+ let qintra = INDEO4_Q8_INTRA[qidx];
+ let qinter = INDEO4_Q8_INTER[qidx];
+ txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan));
+ } else if scan_idx < 10 {
+ validate!(!tr.is_8x8());
+ validate!((qmat_idx >= 15) && (qmat_idx < 22));
+ let scan = INDEO4_SCANS_4X4[scan_idx - 5];
+ let qidx = INDEO4_Q4X4_IDX[qmat_idx - 15];
+ let qintra = INDEO4_Q4_INTRA[qidx];
+ let qinter = INDEO4_Q4_INTER[qidx];
+ txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan));
+ } else {
+ unreachable!();
+ }
+ } else {
+ tr = IVITransformType::None(TSize::T8x8);
+ txtype = TxType::None;
+ }
+
+ let blk_cb;
+ if br.read_bool()? {
+
+ blk_cb = br.read_ivi_codebook_desc(false, true)?;
+ } else {
+ blk_cb = self.blk_cb;
+ }
+ let rvmap_idx;
+ if br.read_bool()? {
+ rvmap_idx = br.read(3)? as usize;
+ } else {
+ rvmap_idx = 8;
+ }
+ let num_corr;
+ let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE];
+ if br.read_bool()? {
+ num_corr = br.read(8)? as usize;
+ validate!(num_corr*2 <= CORR_MAP_SIZE);
+ for i in 0..num_corr*2 {
+ corr_map[i] = br.read(8)? as u8;
+ }
+ } else {
+ num_corr = 0;
+ }
+
+ br.align();
+ Ok(BandHeader::new(plane_no, band_no, mb_size, blk_size, mv_mode == 1, inherit_mv, false, inherit_qd, quant, rvmap_idx, num_corr, corr_map, blk_cb, tr, txtype))
+ }
+
+ fn decode_mb_info(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, band: &BandHeader, tile: &mut IVITile, ref_tile: Option<Ref<IVITile>>, mv_scale: u8) -> DecoderResult<()> {
+ let mut mv_x = 0;
+ let mut mv_y = 0;
+ let mut mb_idx = 0;
+
+ for mb_y in 0..tile.mb_h {
+ for mb_x in 0..tile.mb_w {
+ let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
+ if !br.read_bool()? {
+ if pic_hdr.ftype.is_intra() {
+ mb.mtype = MBType::Intra;
+ } else if band.inherit_mv {
+ if let Some(ref tileref) = ref_tile {
+ mb.mtype = tileref.mb[mb_idx].mtype;
+ } else {
+ return Err(DecoderError::MissingReference);
+ }
+ } else {
+ if !pic_hdr.ftype.is_bidir() {
+ mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
+ } else {
+ mb.mtype = match br.read(2)? {
+ 0 => { MBType::Intra },
+ 1 => { MBType::Inter },
+ 2 => { MBType::Backward },
+ _ => { MBType::Bidir },
+ };
+ }
+ }
+ if band.mb_size == band.blk_size {
+ mb.cbp = br.read(1)? as u8;
+ } else {
+ mb.cbp = br.read(4)? as u8;
+ }
+ if band.inherit_qd {
+ if let Some(ref tileref) = ref_tile {
+ mb.qd = tileref.mb[mb_idx].qd;
+ mb.q = calc_quant(band.quant, mb.qd);
+ } else {
+ mb.q = band.quant as u8;
+ }
+ } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
+ mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
+ mb.q = calc_quant(band.quant, mb.qd);
+ } else {
+ mb.q = band.quant as u8;
+ }
+
+ if mb.mtype != MBType::Intra {
+ if band.inherit_mv {
+ if let Some(ref tileref) = ref_tile {
+ let mx = tileref.mb[mb_idx].mv_x;
+ let my = tileref.mb[mb_idx].mv_y;
+ if mv_scale == 0 {
+ mb.mv_x = mx;
+ mb.mv_y = my;
+ } else {
+ mb.mv_x = scale_mv(mx, mv_scale);
+ mb.mv_y = scale_mv(my, mv_scale);
+ }
+ }
+ } else {
+ mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
+ mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
+ mb.mv_x = mv_x;
+ mb.mv_y = mv_y;
+ if mb.mtype == MBType::Backward {
+ mb.mv2_x = -mb.mv_x;
+ mb.mv2_y = -mb.mv_y;
+ mb.mv_x = 0;
+ mb.mv_y = 0;
+ } else if mb.mtype == MBType::Bidir {
+ mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
+ mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
+ mb.mv2_x = -mv_x;
+ mb.mv2_y = -mv_y;
+ }
+ }
+ }
+ } else {
+ validate!(!pic_hdr.ftype.is_intra());
+ mb.mtype = MBType::Inter;
+ mb.cbp = 0;
+ mb.qd = 0;
+ if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
+ mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
+ mb.q = calc_quant(band.quant, mb.qd);
+ }
+ if band.inherit_mv {
+ if let Some(ref tileref) = ref_tile {
+ let mx = tileref.mb[mb_idx].mv_x;
+ let my = tileref.mb[mb_idx].mv_y;
+ if mv_scale == 0 {
+ mb.mv_x = mx;
+ mb.mv_y = my;
+ } else {
+ mb.mv_x = scale_mv(mx, mv_scale);
+ mb.mv_y = scale_mv(my, mv_scale);
+ }
+ }
+ }
+ }
+ tile.mb[mb_idx] = mb;
+ mb_idx += 1;
+ }
+ }
+ br.align();
+ Ok(())
+ }
+
+ fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
+ let mut idx0 = 0;
+ let mut idx1 = w / 2;
+ let mut idx2 = (h / 2) * sstride;
+ let mut idx3 = idx2 + idx1;
+ let mut oidx0 = 0;
+ let mut oidx1 = dstride;
+
+ for _ in 0..(h/2) {
+ for x in 0..(w/2) {
+ let p0 = src[idx0 + x];
+ let p1 = src[idx1 + x];
+ let p2 = src[idx2 + x];
+ let p3 = src[idx3 + x];
+ dst[oidx0 + x * 2 + 0] = clip8(((p0 + p1 + p2 + p3 + 2) >> 2) + 128);
+ dst[oidx0 + x * 2 + 1] = clip8(((p0 + p1 - p2 - p3 + 2) >> 2) + 128);
+ dst[oidx1 + x * 2 + 0] = clip8(((p0 - p1 + p2 - p3 + 2) >> 2) + 128);
+ dst[oidx1 + x * 2 + 1] = clip8(((p0 - p1 - p2 + p3 + 2) >> 2) + 128);
+ }
+ idx0 += sstride;
+ idx1 += sstride;
+ idx2 += sstride;
+ idx3 += sstride;
+ oidx0 += dstride * 2;
+ oidx1 += dstride * 2;
+ }
+ }
+}
+
+struct Indeo4Decoder {
+ info: Rc<NACodecInfo>,
+ dec: IVIDecoder,
+}
+
+impl Indeo4Decoder {
+ fn new() -> Self {
+ Indeo4Decoder {
+ info: NACodecInfo::new_dummy(),
+ dec: IVIDecoder::new(),
+ }
+ }
+}
+
+impl NADecoder for Indeo4Decoder {
+ fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
+ if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
+ let w = vinfo.get_width();
+ let h = vinfo.get_height();
+ let f = vinfo.is_flipped();
+ let fmt = formats::YUV410_FORMAT;
+ let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
+ self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
+ Ok(())
+ } else {
+ Err(DecoderError::InvalidData)
+ }
+ }
+ fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+ let src = pkt.get_buffer();
+ let mut br = BitReader::new(src.as_slice(), src.len(), BitReaderMode::LE);
+
+ let mut ip = Indeo4Parser::new();
+ let bufinfo = self.dec.decode_frame(&mut ip, &mut br)?;
+ let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
+ frm.set_keyframe(self.dec.is_intra());
+ frm.set_frame_type(self.dec.get_frame_type());
+ Ok(Rc::new(RefCell::new(frm)))
+ }
+}
+
+const INDEO4_PICTURE_SIZE_TAB: [[usize; 2]; 7] = [
+ [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [252, 288], [176, 144]
+];
+
+const INDEO4_SLICE_SIZE_TAB: [usize; 15] = [
+ 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480
+];
+
+const INDEO4_FRAME_TYPE: [IVIFrameType; 7] = [
+ IVIFrameType::Intra, IVIFrameType::Intra1, IVIFrameType::Inter, IVIFrameType::Bidir,
+ IVIFrameType::InterDroppable, IVIFrameType::NULL, IVIFrameType::NULL2
+];
+
+const INDEO4_TRANSFORMS: [IVITransformType; 18] = [
+ IVITransformType::Haar(TSize::T8x8, TDir::TwoD),
+ IVITransformType::Haar(TSize::T8x8, TDir::Row),
+ IVITransformType::Haar(TSize::T8x8, TDir::Col),
+ IVITransformType::None(TSize::T8x8),
+ IVITransformType::Slant(TSize::T8x8, TDir::TwoD),
+ IVITransformType::Slant(TSize::T8x8, TDir::Row),
+ IVITransformType::Slant(TSize::T8x8, TDir::Col),
+ IVITransformType::DCT(TSize::T8x8, TDir::TwoD),
+ IVITransformType::DCT(TSize::T8x8, TDir::Row),
+ IVITransformType::DCT(TSize::T8x8, TDir::Col),
+ IVITransformType::Haar(TSize::T4x4, TDir::TwoD),
+ IVITransformType::Slant(TSize::T4x4, TDir::TwoD),
+ IVITransformType::None(TSize::T4x4),
+ IVITransformType::Haar(TSize::T4x4, TDir::Row),
+ IVITransformType::Haar(TSize::T4x4, TDir::Col),
+ IVITransformType::Slant(TSize::T4x4, TDir::Row),
+ IVITransformType::Slant(TSize::T4x4, TDir::Col),
+ IVITransformType::DCT(TSize::T4x4, TDir::TwoD),
+];
+
+const INDEO4_SCAN_8X8_ALT: [usize; 64] = [
+ 0, 8, 1, 9, 16, 24, 2, 3,
+ 17, 25, 10, 11, 32, 40, 48, 56,
+ 4, 5, 6, 7, 33, 41, 49, 57,
+ 18, 19, 26, 27, 12, 13, 14, 15,
+ 34, 35, 43, 42, 50, 51, 59, 58,
+ 20, 21, 22, 23, 31, 30, 29, 28,
+ 36, 37, 38, 39, 47, 46, 45, 44,
+ 52, 53, 54, 55, 63, 62, 61, 60
+];
+const INDEO4_SCAN_4X4_ALT: [usize; 16] = [ 0, 1, 4, 5, 8, 12, 2, 3, 9, 13, 6, 7, 10, 11, 14, 15 ];
+const INDEO4_SCAN_4X4_VER: [usize; 16] = [ 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 ];
+const INDEO4_SCAN_4X4_HOR: [usize; 16] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ];
+
+const INDEO4_SCANS_8X8: [&[usize; 64]; 5] = [
+ &IVI_ZIGZAG, &INDEO4_SCAN_8X8_ALT, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_VER, &IVI_ZIGZAG
+];
+const INDEO4_SCANS_4X4: [&[usize; 16]; 5] = [
+ &IVI_SCAN_4X4, &INDEO4_SCAN_4X4_ALT, &INDEO4_SCAN_4X4_VER, &INDEO4_SCAN_4X4_HOR, &IVI_SCAN_4X4
+];
+
+const INDEO4_Q8X8_IDX: [usize; 15] = [ 0, 1, 0, 2, 1, 3, 0, 4, 1, 5, 0, 1, 6, 7, 8 ];
+const INDEO4_Q4X4_IDX: [usize; 7] = [ 0, 1, 2, 2, 3, 3, 4 ];
+
+const INDEO4_QUANT8X8_INTRA: [[u16; 64]; 9] = [
+ [
+ 43, 342, 385, 470, 555, 555, 598, 726,
+ 342, 342, 470, 513, 555, 598, 726, 769,
+ 385, 470, 555, 555, 598, 726, 726, 811,
+ 470, 470, 555, 555, 598, 726, 769, 854,
+ 470, 555, 555, 598, 683, 726, 854, 1025,
+ 555, 555, 598, 683, 726, 854, 1025, 1153,
+ 555, 555, 598, 726, 811, 982, 1195, 1451,
+ 555, 598, 726, 811, 982, 1195, 1451, 1793
+ ], [
+ 86, 1195, 2390, 2390, 4865, 4865, 4865, 4865,
+ 1195, 1195, 2390, 2390, 4865, 4865, 4865, 4865,
+ 2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827,
+ 2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827,
+ 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
+ 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
+ 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827,
+ 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827
+ ], [
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835,
+ 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835
+ ], [
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414,
+ 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414
+ ], [
+ 897, 897, 897, 897, 897, 897, 897, 897,
+ 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067,
+ 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238,
+ 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409,
+ 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579,
+ 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
+ 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921,
+ 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091
+ ], [
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414
+ ], [
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390,
+ 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390
+ ], [
+ 22, 171, 214, 257, 257, 299, 299, 342,
+ 171, 171, 257, 257, 299, 299, 342, 385,
+ 214, 257, 257, 299, 299, 342, 342, 385,
+ 257, 257, 257, 299, 299, 342, 385, 427,
+ 257, 257, 299, 299, 342, 385, 427, 513,
+ 257, 299, 299, 342, 385, 427, 513, 598,
+ 299, 299, 299, 385, 385, 470, 598, 726,
+ 299, 299, 385, 385, 470, 598, 726, 897
+ ], [
+ 86, 598, 1195, 1195, 2390, 2390, 2390, 2390,
+ 598, 598, 1195, 1195, 2390, 2390, 2390, 2390,
+ 1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414,
+ 1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414,
+ 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
+ 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
+ 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414,
+ 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414
+ ]
+];
+const INDEO4_QUANT8X8_INTER: [[u16; 64]; 9] = [
+ [
+ 427, 427, 470, 427, 427, 427, 470, 470,
+ 427, 427, 470, 427, 427, 427, 470, 470,
+ 470, 470, 470, 470, 470, 470, 470, 470,
+ 427, 427, 470, 470, 427, 427, 470, 470,
+ 427, 427, 470, 427, 427, 427, 470, 470,
+ 427, 427, 470, 427, 427, 427, 470, 470,
+ 470, 470, 470, 470, 470, 470, 470, 470,
+ 470, 470, 470, 470, 470, 470, 470, 470
+ ], [
+ 1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414,
+ 1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414,
+ 2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822,
+ 2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822,
+ 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
+ 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
+ 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414,
+ 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414
+ ], [
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281,
+ 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281
+ ], [
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433,
+ 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433
+ ], [
+ 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
+ 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
+ 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
+ 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238,
+ 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
+ 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
+ 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
+ 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281
+ ], [
+ 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
+ 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
+ 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414,
+ 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
+ 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
+ 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433,
+ 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433
+ ], [
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707,
+ 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707
+ ], [
+ 86, 171, 171, 214, 214, 214, 214, 257,
+ 171, 171, 214, 214, 214, 214, 257, 257,
+ 171, 214, 214, 214, 214, 257, 257, 257,
+ 214, 214, 214, 214, 257, 257, 257, 299,
+ 214, 214, 214, 257, 257, 257, 299, 299,
+ 214, 214, 257, 257, 257, 299, 299, 299,
+ 214, 257, 257, 257, 299, 299, 299, 342,
+ 257, 257, 257, 299, 299, 299, 342, 342
+ ], [
+ 854, 854, 1195, 1195, 1707, 1707, 1707, 1707,
+ 854, 854, 1195, 1195, 1707, 1707, 1707, 1707,
+ 1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390,
+ 1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390,
+ 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
+ 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
+ 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707,
+ 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707
+ ]
+];
+const INDEO4_QUANT4X4_INTRA: [[u16; 16]; 5] = [
+ [
+ 22, 214, 257, 299,
+ 214, 257, 299, 342,
+ 257, 299, 342, 427,
+ 299, 342, 427, 513
+ ], [
+ 129, 1025, 1451, 1451,
+ 1025, 1025, 1451, 1451,
+ 1451, 1451, 2049, 2049,
+ 1451, 1451, 2049, 2049
+ ], [
+ 43, 171, 171, 171,
+ 43, 171, 171, 171,
+ 43, 171, 171, 171,
+ 43, 171, 171, 171
+ ], [
+ 43, 43, 43, 43,
+ 171, 171, 171, 171,
+ 171, 171, 171, 171,
+ 171, 171, 171, 171
+ ], [
+ 43, 43, 43, 43,
+ 43, 43, 43, 43,
+ 43, 43, 43, 43,
+ 43, 43, 43, 43
+ ]
+];
+const INDEO4_QUANT4X4_INTER: [[u16; 16]; 5] = [
+ [
+ 107, 214, 257, 299,
+ 214, 257, 299, 299,
+ 257, 299, 299, 342,
+ 299, 299, 342, 342
+ ], [
+ 513, 1025, 1238, 1238,
+ 1025, 1025, 1238, 1238,
+ 1238, 1238, 1451, 1451,
+ 1238, 1238, 1451, 1451
+ ], [
+ 43, 171, 171, 171,
+ 43, 171, 171, 171,
+ 43, 171, 171, 171,
+ 43, 171, 171, 171
+ ], [
+ 43, 43, 43, 43,
+ 171, 171, 171, 171,
+ 171, 171, 171, 171,
+ 171, 171, 171, 171
+ ], [
+ 43, 43, 43, 43,
+ 43, 43, 43, 43,
+ 43, 43, 43, 43,
+ 43, 43, 43, 43
+ ]
+];
+const INDEO4_Q8_INTRA: [&[u16; 64]; 9] = [
+ &INDEO4_QUANT8X8_INTRA[0], &INDEO4_QUANT8X8_INTRA[1], &INDEO4_QUANT8X8_INTRA[2],
+ &INDEO4_QUANT8X8_INTRA[3], &INDEO4_QUANT8X8_INTRA[4], &INDEO4_QUANT8X8_INTRA[5],
+ &INDEO4_QUANT8X8_INTRA[6], &INDEO4_QUANT8X8_INTRA[7], &INDEO4_QUANT8X8_INTRA[8],
+];
+const INDEO4_Q8_INTER: [&[u16; 64]; 9] = [
+ &INDEO4_QUANT8X8_INTER[0], &INDEO4_QUANT8X8_INTER[1], &INDEO4_QUANT8X8_INTER[2],
+ &INDEO4_QUANT8X8_INTER[3], &INDEO4_QUANT8X8_INTER[4], &INDEO4_QUANT8X8_INTER[5],
+ &INDEO4_QUANT8X8_INTER[6], &INDEO4_QUANT8X8_INTER[7], &INDEO4_QUANT8X8_INTER[8],
+];
+const INDEO4_Q4_INTRA: [&[u16; 16]; 5] = [
+ &INDEO4_QUANT4X4_INTRA[0], &INDEO4_QUANT4X4_INTRA[1], &INDEO4_QUANT4X4_INTRA[2],
+ &INDEO4_QUANT4X4_INTRA[3], &INDEO4_QUANT4X4_INTRA[4]
+];
+const INDEO4_Q4_INTER: [&[u16; 16]; 5] = [
+ &INDEO4_QUANT4X4_INTER[0], &INDEO4_QUANT4X4_INTER[1], &INDEO4_QUANT4X4_INTER[2],
+ &INDEO4_QUANT4X4_INTER[3], &INDEO4_QUANT4X4_INTER[4]
+];
+
+pub fn get_decoder() -> Box<NADecoder> {
+ Box::new(Indeo4Decoder::new())
+}
+
+#[cfg(test)]
+mod test {
+ use test::dec_video::test_file_decoding;
+ #[test]
+ fn test_indeo4() {
+ test_file_decoding("avi", "assets/IV4/volcano.avi", /*None*/Some(16), true, false, Some("iv4"));
+panic!("the end");
+ }
+}
--- /dev/null
+use std::cell::Ref;
+use io::bitreader::*;
+use formats;
+use super::super::*;
+use super::ivi::*;
+use super::ivibr::*;
+
+fn calc_quant(glob_q: u32, qd: i16) -> usize {
+ let qq = (glob_q as i16) + (qd as i16);
+ if qq < 0 {
+ 0
+ } else if qq > 23 {
+ 23
+ } else {
+ qq as usize
+ }
+}
+
+struct Indeo5Parser {
+ mb_cb: IVICodebook,
+
+ width: usize,
+ height: usize,
+ tile_w: usize,
+ tile_h: usize,
+ luma_bands: usize,
+ chroma_bands: usize,
+
+ is_hpel: [bool; 5],
+ mb_size: [usize; 5],
+ blk_size: [usize; 5],
+}
+
+impl Indeo5Parser {
+ fn new() -> Self {
+ Indeo5Parser {
+ mb_cb: IVI_CB_ZERO,
+
+ width: 0,
+ height: 0,
+ tile_w: 0,
+ tile_h: 0,
+ luma_bands: 0,
+ chroma_bands: 0,
+
+ is_hpel: [false; 5],
+ mb_size: [0; 5],
+ blk_size: [0; 5],
+ }
+ }
+}
+
+fn skip_extension(br: &mut BitReader) -> DecoderResult<()> {
+ loop {
+ let len = br.read(8)?;
+ if len == 0 { break; }
+ br.skip(len * 8)?;
+ }
+ Ok(())
+}
+
+impl IndeoXParser for Indeo5Parser {
+#[allow(unused_variables)]
+#[allow(unused_assignments)]
+ fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> {
+ let sync = br.read(5)?;
+ validate!(sync == 0x1F);
+ let ftype_idx = br.read(3)?;
+ validate!(ftype_idx < 5);
+ let ftype = INDEO5_FRAME_TYPE[ftype_idx as usize];
+ let fnum = br.read(8)?;
+ if ftype == IVIFrameType::Intra {
+ let gop_flags = br.read(8)?;
+ let hdr_size;
+ if (gop_flags & 0x01) != 0 {
+ hdr_size = br.read(16)?;
+ } else {
+ hdr_size = 0;
+ }
+ if (gop_flags & 0x20) != 0 {
+ br.skip(32)?; // lock word
+ }
+ self.tile_w = 0;
+ self.tile_h = 0;
+ if (gop_flags & 0x40) != 0 {
+ self.tile_w = 64 << br.read(2)?;
+ self.tile_h = self.tile_w;
+ }
+ validate!(self.tile_w < 256);
+ self.luma_bands = (br.read(2)? * 3 + 1) as usize;
+ self.chroma_bands = (br.read(1)? * 3 + 1) as usize;
+ validate!((self.luma_bands == 4) || (self.luma_bands == 1));
+ validate!(self.chroma_bands == 1);
+ let pic_size_idx = br.read(4)? as usize;
+ let w;
+ let h;
+ if pic_size_idx < 15 {
+ w = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][0];
+ h = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][1];
+ } else {
+ h = br.read(13)? as usize;
+ w = br.read(13)? as usize;
+ }
+ validate!((w != 0) && (h != 0));
+ self.width = w;
+ self.height = h;
+
+ validate!((gop_flags & 0x02) == 0);
+ if self.tile_w == 0 {
+ self.tile_w = w;
+ self.tile_h = h;
+ }
+ for b in 0..self.luma_bands+self.chroma_bands {
+ self.is_hpel[b] = br.read_bool()?;
+ let mb_scale = br.read(1)?;
+ self.blk_size[b] = 8 >> br.read(1)?;
+ self.mb_size[b] = self.blk_size[b] << (1 - mb_scale);
+ let ext_tr = br.read_bool()?;
+ validate!(!ext_tr);
+ let end_marker = br.read(2)?;
+ validate!(end_marker == 0);
+ }
+ if (gop_flags & 0x08) != 0 {
+ let align = br.read(3)?;
+ validate!(align == 0);
+ if br.read_bool()? {
+ br.skip(24)?; // transparency color
+ }
+ }
+ br.align();
+ br.skip(23)?;
+ if br.read_bool()? { // gop extension
+ loop {
+ let v = br.read(16)?;
+ if (v & 0x8000) == 0 { break; }
+ }
+ }
+ br.align();
+ }
+ if ftype.is_null() {
+ br.align();
+ return Ok(PictureHeader::new_null(ftype));
+ }
+ let flags = br.read(8)?;
+ let size;
+ if (flags & 0x01) != 0 {
+ size = br.read(24)?;
+ } else {
+ size = 0;
+ }
+ let checksum;
+ if (flags & 0x10) != 0 {
+ checksum = br.read(16)?;
+ } else {
+ checksum = 0;
+ }
+ if (flags & 0x20) != 0 {
+ skip_extension(br)?;
+ }
+ let in_q = (flags & 0x08) != 0;
+ self.mb_cb = br.read_ivi_codebook_desc(true, (flags & 0x40) != 0)?;
+ br.skip(3)?;
+ br.align();
+
+ Ok(PictureHeader::new(ftype, self.width, self.height, self.tile_w, self.tile_h, false, self.luma_bands, self.chroma_bands, in_q))
+ }
+
+#[allow(unused_variables)]
+ fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane_no: usize, band_no: usize) -> DecoderResult<BandHeader> {
+ let band_flags = br.read(8)?;
+
+ if (band_flags & 0x01) != 0 {
+ br.align();
+ return Ok(BandHeader::new_empty(plane_no, band_no));
+ }
+ let inherit_mv = (band_flags & 0x02) != 0;
+ let has_qdelta = (band_flags & 0x04) != 0;
+ let inherit_qd = ((band_flags & 0x08) != 0) || !has_qdelta;
+ let data_size: usize;
+ if (band_flags & 0x80) != 0 {
+ data_size = br.read(24)? as usize;
+ } else {
+ data_size = 0;
+ }
+ validate!(data_size <= ((br.left() / 8) as usize));
+
+ let num_corr: usize;
+ let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE];
+ if (band_flags & 0x10) != 0 {
+ num_corr = br.read(8)? as usize;
+ validate!(num_corr*2 <= CORR_MAP_SIZE);
+ for i in 0..num_corr*2 {
+ corr_map[i] = br.read(8)? as u8;
+ }
+ } else {
+ num_corr = 0;
+ }
+ let rvmap_idx;
+ if (band_flags & 0x40) != 0 {
+ rvmap_idx = br.read(3)? as usize;
+ } else {
+ rvmap_idx = 8;
+ }
+ let blk_cb = br.read_ivi_codebook_desc(false, (band_flags & 0x80) != 0)?;
+ if br.read_bool()? {
+ br.skip(16)?; // checksum
+ }
+ let band_q = br.read(5)?;
+ if (band_flags & 0x20) != 0 {
+ skip_extension(br)?;
+ }
+ br.align();
+
+ let tr;
+ let txtype;
+ let band_id = if plane_no == 0 { band_no } else { self.luma_bands };
+ match plane_no {
+ 0 => {
+ let scan = INDEO5_SCAN8X8[band_no];
+ let qintra;
+ let qinter;
+ validate!(self.blk_size[band_id] == 8);
+ match band_no {
+ 0 => {
+ tr = IVITransformType::Slant(TSize::T8x8, TDir::TwoD);
+ if self.luma_bands == 1 {
+ qintra = INDEO5_Q8_INTRA[0];
+ qinter = INDEO5_Q8_INTER[0];
+ } else {
+ qintra = INDEO5_Q8_INTRA[1];
+ qinter = INDEO5_Q8_INTER[1];
+ }
+ },
+ 1 => {
+ tr = IVITransformType::Slant(TSize::T8x8, TDir::Row);
+ qintra = INDEO5_Q8_INTRA[2];
+ qinter = INDEO5_Q8_INTER[2];
+ },
+ 2 => {
+ tr = IVITransformType::Slant(TSize::T8x8, TDir::Col);
+ qintra = INDEO5_Q8_INTRA[3];
+ qinter = INDEO5_Q8_INTER[3];
+ },
+ 3 => {
+ tr = IVITransformType::None(TSize::T8x8);
+ qintra = INDEO5_Q8_INTRA[4];
+ qinter = INDEO5_Q8_INTER[4];
+ },
+ _ => { unreachable!(); }
+ };
+ txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan));
+ },
+ 1 | 2 => {
+ validate!(self.blk_size[band_id] == 4);
+ tr = IVITransformType::Slant(TSize::T4x4, TDir::TwoD);
+ let scan = INDEO5_SCAN4X4;
+ let qintra = INDEO5_Q4_INTRA;
+ let qinter = INDEO5_Q4_INTER;
+ txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan));
+ },
+ _ => { unreachable!(); }
+ };
+
+ 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))
+ }
+
+ fn decode_mb_info(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, band: &BandHeader, tile: &mut IVITile, ref_tile: Option<Ref<IVITile>>, mv_scale: u8) -> DecoderResult<()> {
+ let mut mv_x = 0;
+ let mut mv_y = 0;
+ let band_id = if pic_hdr.luma_bands == 4 { band.band_no + 1 } else { 0 };
+ let mut mb_idx = 0;
+ for mb_y in 0..tile.mb_h {
+ for mb_x in 0..tile.mb_w {
+ let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
+ if !br.read_bool()? {
+ if pic_hdr.ftype.is_intra() {
+ mb.mtype = MBType::Intra;
+ } else if band.inherit_mv {
+ if let Some(ref tileref) = ref_tile {
+ mb.mtype = tileref.mb[mb_idx].mtype;
+ } else {
+ return Err(DecoderError::MissingReference);
+ }
+ } else {
+ mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra };
+ }
+ if band.mb_size == band.blk_size {
+ mb.cbp = br.read(1)? as u8;
+ } else {
+ mb.cbp = br.read(4)? as u8;
+ }
+ let q;
+ if band.has_qdelta {
+ if band.inherit_qd {
+ if let Some(ref tileref) = ref_tile {
+ mb.qd = tileref.mb[mb_idx].qd;
+ q = calc_quant(band.quant, mb.qd);
+ } else {
+ return Err(DecoderError::MissingReference);
+ }
+ } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) {
+ mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
+ q = calc_quant(band.quant, mb.qd);
+ } else {
+ q = band.quant as usize;
+ }
+ } else {
+ q = band.quant as usize;
+ }
+
+ if mb.mtype == MBType::Intra {
+ if band.blk_size == 8 {
+ mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
+ } else {
+ mb.q = INDEO5_QSCALE4_INTRA[q];
+ }
+ } else {
+ if band.blk_size == 8 {
+ mb.q = INDEO5_QSCALE8_INTER[band_id][q];
+ } else {
+ mb.q = INDEO5_QSCALE4_INTER[q];
+ }
+ }
+
+ if mb.mtype != MBType::Intra {
+ if band.inherit_mv {
+ if let Some(ref tileref) = ref_tile {
+ let mx = tileref.mb[mb_idx].mv_x;
+ let my = tileref.mb[mb_idx].mv_y;
+ if mv_scale == 0 {
+ mb.mv_x = mx;
+ mb.mv_y = my;
+ } else {
+ mb.mv_x = scale_mv(mx, mv_scale);
+ mb.mv_y = scale_mv(my, mv_scale);
+ }
+ }
+ } else {
+ mv_y += br.read_ivi_cb_s(&self.mb_cb)?;
+ mv_x += br.read_ivi_cb_s(&self.mb_cb)?;
+ mb.mv_x = mv_x;
+ mb.mv_y = mv_y;
+ }
+ }
+ } else {
+ validate!(!pic_hdr.ftype.is_intra());
+ mb.mtype = MBType::Inter;
+ mb.cbp = 0;
+ mb.qd = 0;
+ if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q {
+ mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16;
+ let q = calc_quant(band.quant, mb.qd);
+ if mb.mtype == MBType::Intra {
+ if band.blk_size == 8 {
+ mb.q = INDEO5_QSCALE8_INTRA[band_id][q];
+ } else {
+ mb.q = INDEO5_QSCALE4_INTRA[q];
+ }
+ } else {
+ if band.blk_size == 8 {
+ mb.q = INDEO5_QSCALE8_INTER[band_id][q];
+ } else {
+ mb.q = INDEO5_QSCALE4_INTER[q];
+ }
+ }
+ }
+ if band.inherit_mv {
+ if let Some(ref tileref) = ref_tile {
+ let mx = tileref.mb[mb_idx].mv_x;
+ let my = tileref.mb[mb_idx].mv_y;
+ if mv_scale == 0 {
+ mb.mv_x = mx;
+ mb.mv_y = my;
+ } else {
+ mb.mv_x = scale_mv(mx, mv_scale);
+ mb.mv_y = scale_mv(my, mv_scale);
+ }
+ }
+ }
+ }
+ tile.mb[mb_idx] = mb;
+ mb_idx += 1;
+ }
+ }
+ br.align();
+ Ok(())
+ }
+
+ fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) {
+ let mut idx0 = 0;
+ let mut idx1 = w / 2;
+ let mut idx2 = (h / 2) * sstride;
+ let mut idx3 = idx2 + idx1;
+ let mut bidx1 = idx1;
+ let mut bidx3 = idx3;
+ let mut oidx0 = 0;
+ let mut oidx1 = dstride;
+ let filt_lo = |a: i16, b: i16| a + b;
+ let filt_hi = |a: i16, b: i16, c: i16| a - b * 6 + c;
+
+ for _ in 0..(h/2) {
+ let mut b0_1 = src[idx0];
+ let mut b0_2 = src[idx0 + sstride];
+ let mut b1_1 = src[bidx1];
+ let mut b1_2 = src[idx1];
+ let mut b1_3 = filt_hi(b1_1, b1_2, src[idx1 + sstride]);
+ let mut b2_1;
+ let mut b2_2 = src[idx2];
+ let mut b2_3 = b2_2;
+ let mut b2_4;
+ let mut b2_5 = src[idx2 + sstride];
+ let mut b2_6 = b2_5;
+ let mut b3_1;
+ let mut b3_2 = src[bidx3];
+ let mut b3_3 = b3_2;
+ let mut b3_4;
+ let mut b3_5 = src[idx3];
+ let mut b3_6 = b3_5;
+ let mut b3_8 = filt_hi(b3_2, b3_5, src[idx3 + sstride]);
+ let mut b3_9 = b3_8;
+ let mut b3_7;
+
+ for x in 0..(w/2) {
+ b2_1 = b2_2;
+ b2_2 = b2_3;
+ b2_4 = b2_5;
+ b2_5 = b2_6;
+ b3_1 = b3_2;
+ b3_2 = b3_3;
+ b3_4 = b3_5;
+ b3_5 = b3_6;
+ b3_7 = b3_8;
+ b3_8 = b3_9;
+
+ let tmp0 = b0_1;
+ let tmp1 = b0_2;
+ b0_1 = src[idx0 + x + 1];
+ b0_2 = src[idx0 + x + 1 + sstride];
+ let mut p0 = tmp0 << 4;
+ let mut p1 = (tmp0 + b0_1) << 3;
+ let mut p2 = (tmp0 + tmp1) << 3;
+ let mut p3 = (tmp0 + tmp1 + b0_1 + b0_2) << 2;
+
+ let tmp0 = b1_1;
+ let tmp1 = b1_2;
+ let tmp2 = filt_lo(tmp0, tmp1);
+ let tmp3 = filt_hi(tmp0, tmp1, b1_3);
+ b1_2 = src[ idx1 + x + 1];
+ b1_1 = src[bidx1 + x + 1];
+ b1_3 = filt_hi(b1_1, b1_2, src[idx1 + x + 1 + sstride]);
+ p0 += tmp2 << 3;
+ p1 += (tmp2 + b1_1 + b1_2) << 2;
+ p2 += tmp3 << 2;
+ p3 += (tmp3 + b1_3) << 1;
+
+ b2_3 = src[idx2 + x + 1];
+ b2_6 = src[idx2 + x + 1 + sstride];
+ let tmp0 = filt_lo(b2_1, b2_2);
+ let tmp1 = filt_hi(b2_1, b2_2, b2_3);
+ p0 += tmp0 << 3;
+ p1 += tmp1 << 2;
+ p2 += (tmp0 + filt_lo(b2_4, b2_5)) << 2;
+ p3 += (tmp1 + filt_hi(b2_4, b2_5, b2_6)) << 1;
+
+ b3_6 = src[idx3 + x + 1];
+ b3_3 = src[bidx3 + x + 1];
+ b3_9 = filt_hi(b3_3, b3_6, src[idx3 + x + 1 + sstride]);
+ let tmp0 = b3_1 + b3_4;
+ let tmp1 = b3_2 + b3_5;
+ let tmp2 = b3_3 + b3_6;
+ p0 += filt_lo(tmp0, tmp1) << 2;
+ p1 += filt_hi(tmp0, tmp1, tmp2) << 1;
+ p2 += filt_lo(b3_7, b3_8) << 1;
+ p3 += filt_hi(b3_7, b3_8, b3_9) << 0;
+
+ dst[oidx0 + x * 2 + 0] = clip8((p0 >> 6) + 128);
+ dst[oidx0 + x * 2 + 1] = clip8((p1 >> 6) + 128);
+ dst[oidx1 + x * 2 + 0] = clip8((p2 >> 6) + 128);
+ dst[oidx1 + x * 2 + 1] = clip8((p3 >> 6) + 128);
+ }
+ bidx1 = idx1;
+ bidx3 = idx3;
+ idx0 += sstride;
+ idx1 += sstride;
+ idx2 += sstride;
+ idx3 += sstride;
+ oidx0 += dstride * 2;
+ oidx1 += dstride * 2;
+ }
+ }
+}
+
+struct Indeo5Decoder {
+ info: Rc<NACodecInfo>,
+ dec: IVIDecoder,
+ ip: Indeo5Parser,
+}
+
+impl Indeo5Decoder {
+ fn new() -> Self {
+ Indeo5Decoder {
+ info: NACodecInfo::new_dummy(),
+ dec: IVIDecoder::new(),
+ ip: Indeo5Parser::new(),
+ }
+ }
+}
+
+impl NADecoder for Indeo5Decoder {
+ fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
+ if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
+ let w = vinfo.get_width();
+ let h = vinfo.get_height();
+ let f = vinfo.is_flipped();
+ let fmt = formats::YUV410_FORMAT;
+ let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
+ self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
+ Ok(())
+ } else {
+ Err(DecoderError::InvalidData)
+ }
+ }
+ fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+ let src = pkt.get_buffer();
+ let mut br = BitReader::new(src.as_slice(), src.len(), BitReaderMode::LE);
+
+ let bufinfo = self.dec.decode_frame(&mut self.ip, &mut br)?;
+ let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
+ frm.set_keyframe(self.dec.is_intra());
+ frm.set_frame_type(self.dec.get_frame_type());
+ Ok(Rc::new(RefCell::new(frm)))
+ }
+}
+
+const INDEO5_PICTURE_SIZE_TAB: [[usize; 2]; 15] = [
+ [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144],
+ [240, 180], [640, 240], [704, 240], [80, 60], [88, 72], [0, 0], [0, 0], [0, 0]
+];
+
+const INDEO5_FRAME_TYPE: [IVIFrameType; 5] = [
+ IVIFrameType::Intra, IVIFrameType::Inter, IVIFrameType::InterScal,
+ IVIFrameType::InterDroppable, IVIFrameType::NULL,
+];
+
+const INDEO5_QUANT8X8_INTRA: [[u16; 64]; 5] = [
+ [
+ 0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a,
+ 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a,
+ 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72,
+ 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a,
+ 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e,
+ 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6,
+ 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca,
+ 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe,
+ ], [
+ 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
+ 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
+ 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
+ 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
+ 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
+ 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
+ 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
+ 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
+ ], [
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ ], [
+ 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+ 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
+ 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
+ ], [
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ ]
+];
+const INDEO5_QUANT8X8_INTER: [[u16; 64]; 5] = [
+ [
+ 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
+ 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
+ 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
+ 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
+ 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
+ 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
+ 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
+ 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
+ ], [
+ 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a,
+ 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e,
+ 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62,
+ 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66,
+ 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a,
+ 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e,
+ 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72,
+ 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76,
+ ], [
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2,
+ ], [
+ 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+ 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+ 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
+ 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+ 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2,
+ ], [
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
+ ]
+];
+const INDEO5_QUANT4X4_INTRA: [u16; 16] = [
+ 0x1e, 0x3e, 0x4a, 0x52,
+ 0x3e, 0x4a, 0x52, 0x5e,
+ 0x4a, 0x52, 0x5e, 0x7a,
+ 0x52, 0x5e, 0x7a, 0x92
+];
+const INDEO5_QUANT4X4_INTER: [u16; 16] = [
+ 0x1e, 0x3e, 0x4a, 0x52,
+ 0x3e, 0x4a, 0x52, 0x56,
+ 0x4a, 0x52, 0x56, 0x5e,
+ 0x52, 0x56, 0x5e, 0x66
+];
+const INDEO5_Q8_INTRA: [&[u16; 64]; 5] = [
+ &INDEO5_QUANT8X8_INTRA[0], &INDEO5_QUANT8X8_INTRA[1], &INDEO5_QUANT8X8_INTRA[2],
+ &INDEO5_QUANT8X8_INTRA[3], &INDEO5_QUANT8X8_INTRA[4],
+];
+const INDEO5_Q8_INTER: [&[u16; 64]; 5] = [
+ &INDEO5_QUANT8X8_INTER[0], &INDEO5_QUANT8X8_INTER[1], &INDEO5_QUANT8X8_INTER[2],
+ &INDEO5_QUANT8X8_INTER[3], &INDEO5_QUANT8X8_INTER[4],
+];
+const INDEO5_Q4_INTRA: &[u16; 16] = &INDEO5_QUANT4X4_INTRA;
+const INDEO5_Q4_INTER: &[u16; 16] = &INDEO5_QUANT4X4_INTER;
+
+const INDEO5_SCAN8X8: [&[usize; 64]; 4] = [
+ &IVI_ZIGZAG, &IVI_SCAN_8X8_VER, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_HOR
+];
+const INDEO5_SCAN4X4: &[usize; 16] = &IVI_SCAN_4X4;
+
+const INDEO5_QSCALE8_INTRA: [[u8; 24]; 5] = [
+ [
+ 0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20,
+ 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c,
+ ], [
+ 0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c,
+ 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c,
+ ], [
+ 0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e,
+ 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95,
+ ], [
+ 0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d,
+ 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b,
+ ], [
+ 0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b,
+ 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4,
+ ]
+];
+const INDEO5_QSCALE8_INTER: [[u8; 24]; 5] = [
+ [
+ 0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22,
+ 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a,
+ ], [
+ 0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35,
+ 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e,
+ ], [
+ 0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51,
+ 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97,
+ ], [
+ 0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39,
+ 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62,
+ ], [
+ 0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80,
+ 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba
+ ]
+];
+const INDEO5_QSCALE4_INTRA: [u8; 24] = [
+ 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
+];
+const INDEO5_QSCALE4_INTER: [u8; 24] = [
+ 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
+];
+
+pub fn get_decoder() -> Box<NADecoder> {
+ Box::new(Indeo5Decoder::new())
+}
+
+#[cfg(test)]
+mod test {
+ use test::dec_video::test_file_decoding;
+ #[test]
+ fn test_indeo5() {
+ test_file_decoding("avi", "assets/IV5/sample.avi", /*None*/Some(2), true, false, None);
+// test_file_decoding("avi", "assets/IV5/W32mdl_1.avi", None/*Some(2)*/, true, false, Some("iv5"));
+//panic!("the end");
+ }
+}
--- /dev/null
+use std::mem;
+use std::rc::Rc;
+use std::cell::{Ref,RefCell};
+use io::bitreader::*;
+use io::intcode::*;
+use super::super::*;
+use formats::*;
+use super::ivi::*;
+use super::ividsp::*;
+
+pub fn scale_mv(val: i32, scale: u8) -> i32 {
+ (val + (if val > 0 { 1 } else { 0 }) + (scale as i32) - 1) >> scale
+}
+
+#[derive(Clone,Copy)]
+pub struct IVICodebook {
+ len: usize,
+ bits: [u8; 16],
+// offs: [u32; 16],
+}
+
+/*impl IVICodebook {
+ pub fn init(&self) -> Self {
+ let mut cb = self;
+ let mut base: u32 = 0;
+ for i in 0..cb.len {
+ cb.offs[i] = base;
+ base += 1 << cb.bits[i];
+ }
+ cb
+ }
+}*/
+
+pub const IVI_CB_ZERO: IVICodebook = IVICodebook { len: 0, bits: [0; 16] };
+
+pub trait IVICodebookReader {
+ fn read_ivi_codebook_desc(&mut self, mb_cb: bool, try_default: bool) -> DecoderResult<IVICodebook>;
+ fn read_ivi_cb(&mut self, cb: &IVICodebook) -> BitReaderResult<u32>;
+ fn read_ivi_cb_s(&mut self, cb: &IVICodebook) -> BitReaderResult<i32>;
+}
+
+impl<'a> IVICodebookReader for BitReader<'a> {
+ fn read_ivi_codebook_desc(&mut self, mb_cb: bool, desc_coded: bool) -> DecoderResult<IVICodebook> {
+ if !desc_coded {
+ if mb_cb {
+ Ok(IVI_MB_CB[7])
+ } else {
+ Ok(IVI_BLK_CB[7])
+ }
+ } else {
+ let idx = self.read(3)? as usize;
+ if idx != 7 {
+ if mb_cb {
+ Ok(IVI_MB_CB[idx])
+ } else {
+ Ok(IVI_BLK_CB[idx])
+ }
+ } else {
+ let mut cb = IVI_CB_ZERO;
+ cb.len = self.read(4)? as usize;
+ if cb.len == 0 { return Err(DecoderError::InvalidData); }
+ for i in 0..cb.len {
+ cb.bits[i] = self.read(4)? as u8;
+ }
+ Ok(cb)
+ }
+ }
+ }
+ fn read_ivi_cb(&mut self, cb: &IVICodebook) -> BitReaderResult<u32> {
+ let pfx = if cb.len == 1 { 0 } else {self.read_code(UintCodeType::LimitedUnary((cb.len - 1) as u32, 0))? as usize };
+ let nbits = cb.bits[pfx];
+//todo: cache offsets or maybe convert to proper codebook
+ let mut base: u32 = 0;
+ for i in 0..pfx { base += 1 << cb.bits[i]; }
+ let rval = self.read(nbits)?;
+ let add = reverse_bits(rval, nbits);
+ Ok(base + add)
+ }
+ fn read_ivi_cb_s(&mut self, cb: &IVICodebook) -> BitReaderResult<i32> {
+ let v = self.read_ivi_cb(cb)?;
+ if v == 0 {
+ Ok(0)
+ } else {
+ let sign = (v & 1) == 1;
+ let val = (v >> 1) as i32;
+ if sign {
+ Ok(val + 1)
+ } else {
+ Ok(-val)
+ }
+ }
+ }
+}
+
+pub const IVI_MB_CB: &[IVICodebook; 8] = &[
+ IVICodebook { len: 8, bits: [ 0, 4, 5, 4, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0 ] },
+ IVICodebook { len: 12, bits: [ 0, 2, 2, 3, 3, 3, 3, 5, 3, 2, 2, 2, 0, 0, 0, 0 ] },
+ IVICodebook { len: 12, bits: [ 0, 2, 3, 4, 3, 3, 3, 3, 4, 3, 2, 2, 0, 0, 0, 0 ] },
+ IVICodebook { len: 12, bits: [ 0, 3, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 0, 0, 0, 0 ] },
+ IVICodebook { len: 13, bits: [ 0, 4, 4, 3, 3, 3, 3, 2, 3, 3, 2, 1, 1, 0, 0, 0 ] },
+ IVICodebook { len: 9, bits: [ 0, 4, 4, 4, 4, 3, 3, 3, 2, 0, 0, 0, 0, 0, 0, 0 ] },
+ IVICodebook { len: 10, bits: [ 0, 4, 4, 4, 4, 3, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0 ] },
+ IVICodebook { len: 12, bits: [ 0, 4, 4, 4, 3, 3, 2, 3, 2, 2, 2, 2, 0, 0, 0, 0 ] }
+];
+
+pub const IVI_BLK_CB: &[IVICodebook; 8] = &[
+ IVICodebook { len: 10, bits: [ 1, 2, 3, 4, 4, 7, 5, 5, 4, 1, 0, 0, 0, 0, 0, 0 ] },
+ IVICodebook { len: 11, bits: [ 2, 3, 4, 4, 4, 7, 5, 4, 3, 3, 2, 0, 0, 0, 0, 0 ] },
+ IVICodebook { len: 12, bits: [ 2, 4, 5, 5, 5, 5, 6, 4, 4, 3, 1, 1, 0, 0, 0, 0 ] },
+ IVICodebook { len: 13, bits: [ 3, 3, 4, 4, 5, 6, 6, 4, 4, 3, 2, 1, 1, 0, 0, 0 ] },
+ IVICodebook { len: 11, bits: [ 3, 4, 4, 5, 5, 5, 6, 5, 4, 2, 2, 0, 0, 0, 0, 0 ] },
+ IVICodebook { len: 13, bits: [ 3, 4, 5, 5, 5, 5, 6, 4, 3, 3, 2, 1, 1, 0, 0, 0 ] },
+ IVICodebook { len: 13, bits: [ 3, 4, 5, 5, 5, 6, 5, 4, 3, 3, 2, 1, 1, 0, 0, 0 ] },
+ IVICodebook { len: 9, bits: [ 3, 4, 4, 5, 5, 5, 6, 5, 5, 0, 0, 0, 0, 0, 0, 0 ] }
+];
+
+#[allow(unused_variables)]
+fn read_trans_band_header(br: &mut BitReader, w: usize, h: usize, dst: &mut [i16], dstride: usize) -> DecoderResult<()> {
+ let color_plane = br.read(2)?;
+ let bit_depth = br.read(3)?;
+ let dirty_rects = br.read(8)? as usize;
+ for i in 0..dirty_rects {
+ let x = br.read(16)?;
+ let y = br.read(16)?;
+ let l = br.read(16)?;
+ let r = br.read(16)?;
+ }
+ let has_trans_color = br.read_bool()?;
+ if has_trans_color {
+ let r = br.read(8)?;
+ let g = br.read(8)?;
+ let b = br.read(8)?;
+ }
+
+ br.skip(1)?;
+
+ let mut cb = IVI_CB_ZERO;
+ cb.len = br.read(4)? as usize;
+ if cb.len == 0 { return Err(DecoderError::InvalidData); }
+ for i in 0..cb.len {
+ cb.bits[i] = br.read(4)? as u8;
+ }
+ br.align();
+
+let tile_start = br.tell();
+ let empty = br.read_bool()?;
+ if !empty {
+ br.read_bool()?;
+ let mut len = br.read(8)? as usize;
+ if len == 255 {
+ len = br.read(24)? as usize;
+ }
+ br.align();
+let tile_end = tile_start + len * 8;
+
+ let first_val = br.read_bool()?;
+
+ let mut dec_size = 0;
+ let mut x = 0;
+ let mut y = 0;
+ let mut fill = if !first_val { 255-128 } else { 0-128 };
+ let tr_w = (w + 31) & !31;
+ while br.tell() < tile_end {
+ let code = br.read_ivi_cb(&cb)? as usize;
+ if code == 0 {
+ dec_size += 255;
+ for _ in 0..255 {
+ if (x < w) && (y < h) {
+ dst[x + y * dstride] = fill;
+ }
+ x += 1;
+ if x == tr_w {
+ x = 0;
+ y += 1;
+ }
+ }
+ } else {
+ dec_size += code;
+ for _ in 0..code {
+ if (x < w) && (y < h) {
+ dst[x + y * dstride] = fill;
+ }
+ x += 1;
+ if x == tr_w {
+ x = 0;
+ y += 1;
+ }
+ }
+ fill = !fill;
+ }
+ }
+ br.align();
+ } else {
+ }
+
+ Ok(())
+}
+
+fn decode_block8x8(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams8x8, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: &TrFunc) -> DecoderResult<()> {
+ let mut idx: isize = -1;
+ let quant_mat = if is_intra { tables.quant_intra } else { tables.quant_inter };
+ while idx <= 64 {
+ let c = br.read_ivi_cb(blk_cb)?;
+ if c == rvmap.eob_sym { break; }
+ let run;
+ let val: i32;
+ if c != rvmap.esc_sym {
+ validate!(c < 256);
+ run = rvmap.runtab[c as usize] as isize;
+ val = rvmap.valtab[c as usize] as i32;
+ } else {
+ run = (br.read_ivi_cb(blk_cb)? as isize) + 1;
+ let lo = br.read_ivi_cb(blk_cb)?;
+ let hi = br.read_ivi_cb(blk_cb)?;
+ let v = (hi << 6) + lo;
+ if v == 0 {
+ val = 0; // should not happen but still...
+ } else {
+ if (v & 1) != 0 {
+ val = ((v >> 1) as i32) + 1;
+ } else {
+ val = -((v >> 1) as i32);
+ }
+ }
+ }
+ idx += run;
+ validate!((idx >= 0) && (idx < 64));
+
+ let spos = tables.scan[idx as usize];
+ let q = ((quant_mat[spos] as u32) * (quant as u32)) >> 9;
+ if q > 1 {
+ let qq = q as i32;
+ let bias = (((q ^ 1) - 1) >> 1) as i32;
+ coeffs[spos] = val * qq;
+ if val > 0 { coeffs[spos] += bias; }
+ else { coeffs[spos] -= bias; }
+ } else {
+ coeffs[spos] = val;
+ }
+ }
+ if is_intra && is_2d {
+ *prev_dc += coeffs[0];
+ coeffs[0] = *prev_dc;
+ }
+ (transform)(coeffs);
+ Ok(())
+}
+fn decode_block4x4(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams4x4, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: &TrFunc) -> DecoderResult<()> {
+ let mut idx: isize = -1;
+ let quant_mat = if is_intra { tables.quant_intra } else { tables.quant_inter };
+ while idx <= 64 {
+ let c = br.read_ivi_cb(blk_cb)?;
+ if c == rvmap.eob_sym { break; }
+ let run;
+ let val: i32;
+ if c != rvmap.esc_sym {
+ validate!(c < 256);
+ run = rvmap.runtab[c as usize] as isize;
+ val = rvmap.valtab[c as usize] as i32;
+ } else {
+ run = (br.read_ivi_cb(blk_cb)? as isize) + 1;
+ let lo = br.read_ivi_cb(blk_cb)?;
+ let hi = br.read_ivi_cb(blk_cb)?;
+ let v = (hi << 5) + lo;
+ if v == 0 {
+ val = 0; // should not happen but still...
+ } else {
+ if (v & 1) != 0 {
+ val = ((v >> 1) as i32) + 1;
+ } else {
+ val = -((v >> 1) as i32);
+ }
+ }
+ }
+ idx += run;
+ validate!((idx >= 0) && (idx < 16));
+
+ let spos = tables.scan[idx as usize];
+ let q = ((quant_mat[spos] as u32) * (quant as u32)) >> 9;
+ if q > 1 {
+ let qq = q as i32;
+ let bias = (((q ^ 1) - 1) >> 1) as i32;
+ coeffs[spos] = val * qq;
+ if val > 0 { coeffs[spos] += bias; }
+ else { coeffs[spos] -= bias; }
+ } else {
+ coeffs[spos] = val;
+ }
+ }
+ if is_intra && is_2d {
+ *prev_dc += coeffs[0];
+ coeffs[0] = *prev_dc;
+ }
+ (transform)(coeffs);
+ Ok(())
+}
+
+fn put_block(frame: &mut [i16], mut offs: usize, stride: usize, blk: &[i32], blk_size: usize) {
+ let mut idx = 0;
+ for _ in 0..blk_size {
+ for i in 0..blk_size {
+ let mut v = blk[idx + i];
+ if v < -32768 { v = -32768; }
+ if v > 32768 { v = 32767; }
+ frame[offs + i] = v as i16;
+ }
+ idx += blk_size;
+ offs += stride;
+ }
+}
+
+fn add_block(frame: &mut [i16], mut offs: usize, stride: usize, blk: &[i32], blk_size: usize) {
+ let mut idx = 0;
+ for _ in 0..blk_size {
+ for i in 0..blk_size {
+ let mut v = blk[idx + i];
+ if v < -32768 { v = -32768; }
+ if v > 32768 { v = 32767; }
+ frame[offs + i] += v as i16;
+ }
+ idx += blk_size;
+ offs += stride;
+ }
+}
+
+struct FrameData {
+ plane_buf: [Vec<i16>; 4],
+ plane_stride: [usize; 4],
+ pic_hdr: PictureHeader,
+}
+
+fn align(val: usize, bits: u8) -> usize {
+ let mask = (1 << bits) - 1;
+ (val + mask) & !mask
+}
+
+impl FrameData {
+ fn new() -> Rc<RefCell<Self>> {
+ Rc::new(RefCell::new(FrameData {
+ plane_buf: [Vec::new(), Vec::new(), Vec::new(), Vec::new()],
+ plane_stride: [0, 0, 0, 0],
+ pic_hdr: PictureHeader::new_null(IVIFrameType::Intra),
+ }))
+ }
+ fn realloc(&mut self, pic_hdr: &PictureHeader) -> DecoderResult<()> {
+ let width = align(pic_hdr.width, 6);
+ let height = align(pic_hdr.height, 6);
+
+ let stride = width;
+ self.plane_buf[0].resize(stride * height, 0);
+ self.plane_stride[0] = stride;
+ for plane in 1..3 {
+ self.plane_buf[plane].resize((stride >> 1) * (height >> 1), 0);
+ self.plane_stride[plane] = stride >> 1;
+ }
+ if pic_hdr.transparent {
+ self.plane_buf[3].resize(stride * height, 0);
+ self.plane_stride[3] = stride;
+ }
+ self.pic_hdr = *pic_hdr;
+ Ok(())
+ }
+ fn fill_plane(&mut self, vb: &mut NAVideoBuffer<u8>, plane: usize) {
+ let (w, h) = vb.get_dimensions(plane);
+ let mut didx = vb.get_offset(plane);
+ let dstride = vb.get_stride(plane);
+ let mut dst = vb.get_data_mut();
+ let src = &self.plane_buf[plane];
+ let mut sidx = 0;
+ let sstride = self.plane_stride[plane];
+ for _ in 0..h {
+ for x in 0..w {
+ dst[didx + x] = clip8(src[sidx + x] + 128);
+ }
+ didx += dstride;
+ sidx += sstride;
+ }
+ }
+}
+
+fn do_mc(dst: &mut [i16], dstride: usize, src: &[i16], sstride: usize, x: usize, y: usize, l: usize, r: usize, t: usize, b: usize, mv_x: i32, mv_y: i32, is_hpel: bool, blk_size: usize) {
+ let (xoff, yoff, mv_mode) = if is_hpel {
+ (mv_x >> 1, mv_y >> 1, ((mv_x & 1) + (mv_y & 1) * 2) as u8)
+ } else{
+ (mv_x, mv_y, 0)
+ };
+ let xpos = (x as isize) + (xoff as isize);
+ let ypos = (y as isize) + (yoff as isize);
+ if (xpos < (l as isize)) || ((xpos as usize) + blk_size + ((mv_mode & 1) as usize) > r) ||
+ (ypos < (t as isize)) || ((ypos as usize) + blk_size + ((mv_mode >> 1) as usize) > b) {
+//println!(" copy from {},{} of {}-{},{}-{} {}x{}!", xpos, ypos, l,r,t,b,blk_size,blk_size);
+ return;
+ }
+ let sidx = (xpos as usize) + (ypos as usize) * sstride;
+ ivi_mc_put(dst, dstride, &src[sidx..], sstride, mv_mode, blk_size, blk_size);
+}
+
+fn do_mc_b(dst: &mut [i16], dstride: usize, src1: &[i16], sstride1: usize, src2: &[i16], sstride2: usize, x: usize, y: usize, l: usize, r: usize, t: usize, b: usize, mv_x: i32, mv_y: i32, mv2_x: i32, mv2_y: i32, is_hpel: bool, blk_size: usize) {
+ let (xoff1, yoff1, mv_mode1) = if is_hpel {
+ (mv_x >> 1, mv_y >> 1, ((mv_x & 1) + (mv_y & 1) * 2) as u8)
+ } else{
+ (mv_x, mv_y, 0)
+ };
+ let xpos1 = (x as isize) + (xoff1 as isize);
+ let ypos1 = (y as isize) + (yoff1 as isize);
+ if (xpos1 < (l as isize)) || ((xpos1 as usize) + blk_size + ((mv_mode1 & 1) as usize) > r) ||
+ (ypos1 < (t as isize)) || ((ypos1 as usize) + blk_size + ((mv_mode1 >> 1) as usize) > b) {
+ return;
+ }
+ let sidx1 = (xpos1 as usize) + (ypos1 as usize) * sstride1;
+ let (xoff2, yoff2, mv_mode2) = if is_hpel {
+ (mv2_x >> 1, mv2_y >> 1, ((mv2_x & 1) + (mv2_y & 1) * 2) as u8)
+ } else{
+ (mv2_x, mv2_y, 0)
+ };
+ let xpos2 = (x as isize) + (xoff2 as isize);
+ let ypos2 = (y as isize) + (yoff2 as isize);
+ if (xpos2 < (l as isize)) || ((xpos2 as usize) + blk_size + ((mv_mode2 & 1) as usize) > r) ||
+ (ypos2 < (t as isize)) || ((ypos2 as usize) + blk_size + ((mv_mode2 >> 1) as usize) > b) {
+ return;
+ }
+ let sidx2 = (xpos2 as usize) + (ypos2 as usize) * sstride2;
+ ivi_mc_avg(dst, dstride, &src1[sidx1..], sstride1, mv_mode1, &src2[sidx2..], sstride2, mv_mode2, blk_size, blk_size);
+}
+
+pub trait IndeoXParser {
+ fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader>;
+ fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane: usize, band: usize) -> DecoderResult<BandHeader>;
+ fn decode_mb_info(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, band_hdr: &BandHeader, tile: &mut IVITile, ref_tile: Option<Ref<IVITile>>, mv_scale: u8) -> DecoderResult<()>;
+ fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize);
+}
+
+const MISSING_REF: usize = 42;
+
+pub struct IVIDecoder {
+ ftype: IVIFrameType,
+ frames: [Rc<RefCell<FrameData>>; 4],
+ cur_frame: usize,
+ prev_frame: usize,
+ next_frame: usize,
+ iref_0: usize,
+ iref_1: usize,
+ scal_ref: usize,
+ vinfo: NAVideoInfo,
+ vinfoa: NAVideoInfo,
+ bref: Option<NABufferType>,
+
+ bands: Vec<BandHeader>,
+ tiles: Vec<Rc<RefCell<IVITile>>>,
+ num_tiles: [[usize; 4]; 4],
+ tile_start: [[usize; 4]; 4],
+}
+
+impl IVIDecoder {
+ pub fn new() -> Self {
+ let mut bands: Vec<BandHeader> = Vec::with_capacity(12);
+ bands.resize(12, BandHeader::new_empty(42, 42));
+ IVIDecoder {
+ ftype: IVIFrameType::NULL,
+ frames: [FrameData::new(), FrameData::new(), FrameData::new(), FrameData::new()],
+ cur_frame: 0, prev_frame: MISSING_REF, next_frame: MISSING_REF,
+ iref_0: MISSING_REF, iref_1: MISSING_REF, scal_ref: MISSING_REF,
+ vinfo: NAVideoInfo::new(0, 0, false, YUV410_FORMAT),
+ vinfoa: NAVideoInfo::new(0, 0, false, YUVA410_FORMAT),
+ bref: None,
+
+ bands: bands,
+ tiles: Vec::new(), tile_start: [[0; 4]; 4], num_tiles: [[0; 4]; 4],
+ }
+ }
+
+ fn realloc(&mut self, pic_hdr: &PictureHeader) -> DecoderResult<()> {
+ let planes = if pic_hdr.transparent { 4 } else { 3 };
+
+ //self.bands.truncate(0);
+ self.tiles.truncate(0);
+ self.num_tiles = [[0; 4]; 4];
+ self.tile_start = [[0; 4]; 4];
+ let mut tstart: usize = 0;
+ for plane in 0..planes {
+ let is_luma = (plane != 1) && (plane != 2);
+ let bands = if is_luma { pic_hdr.luma_bands } else { pic_hdr.chroma_bands };
+ let mut band_w = if is_luma { pic_hdr.width } else { (pic_hdr.width + 3) >> 2 };
+ let mut band_h = if is_luma { pic_hdr.height } else { (pic_hdr.height + 3) >> 2 };
+ let mut tile_w = if is_luma { pic_hdr.slice_w } else { (pic_hdr.slice_w + 3) >> 2 };
+ let mut tile_h = if is_luma { pic_hdr.slice_h } else { (pic_hdr.slice_h + 3) >> 2 };
+ if bands > 1 {
+ band_w = (band_w + 1) >> 1;
+ band_h = (band_h + 1) >> 1;
+ if plane == 0 {
+ tile_w = (tile_w + 1) >> 1;
+ tile_h = (tile_h + 1) >> 1;
+ }
+ }
+ for band in 0..bands {
+ self.tile_start[plane][band] = tstart;
+ let band_xoff = if (band & 1) == 1 { band_w } else { 0 };
+ let band_yoff = if (band & 2) == 2 { band_h } else { 0 };
+ let mut y = 0;
+ while y < band_h {
+ let cur_h = if y + tile_h <= band_h { tile_h } else { band_h - y };
+ let mut x = 0;
+ while x < band_w {
+ let cur_w = if x + tile_w <= band_w { tile_w } else { band_w - x };
+ let tile = IVITile::new(band_xoff + x, band_yoff + y, cur_w, cur_h);
+ self.tiles.push(Rc::new(RefCell::new(tile)));
+ self.num_tiles[plane][band] += 1;
+ tstart += 1;
+ x += tile_w;
+ }
+ y += tile_h;
+ }
+ }
+ }
+ Ok(())
+ }
+ fn decode_band(&mut self, pic_hdr: &PictureHeader, dec: &mut IndeoXParser, br: &mut BitReader, plane_no: usize, band_no: usize) -> DecoderResult<()> {
+ let bidx = match plane_no {
+ 0 => { band_no },
+ _ => { pic_hdr.luma_bands + plane_no - 1 },
+ };
+ let prev_band = if bidx >= self.bands.len() { BandHeader::new_empty(plane_no, band_no) } else { self.bands[bidx].clone() };
+ let mut band = dec.decode_band_header(br, pic_hdr, plane_no, band_no)?;
+ if let TxType::None = band.ttype {
+ validate!(band.plane_no == prev_band.plane_no);
+ validate!(band.band_no == prev_band.band_no);
+ validate!(band.blk_size == prev_band.blk_size);
+ band.tr = prev_band.tr;
+ band.ttype = prev_band.ttype;
+ };
+
+ let tstart = self.tile_start[band.plane_no][band.band_no];
+ let tend = tstart + self.num_tiles[band.plane_no][band.band_no];
+ let mb_size = band.mb_size;
+ let (tr, tr_dc) = match band.ttype {
+ TxType::Transform4(_) => { ivi_get_transform4x4_funcs(band.tr) },
+ TxType::Transform8(_) => { ivi_get_transform8x8_funcs(band.tr) },
+ _ => { ivi_get_transform4x4_funcs(band.tr) },
+ };
+ for tile_no in tstart..tend {
+ {
+ let mut tile = self.tiles[tile_no].borrow_mut();
+ let mb_w = (tile.w + mb_size - 1) / mb_size;
+ let mb_h = (tile.h + mb_size - 1) / mb_size;
+ tile.mb_w = mb_w;
+ tile.mb_h = mb_h;
+ tile.mb.truncate(0);
+ tile.mb.resize(mb_w * mb_h, MB::new(0, 0));
+ }
+
+ let tile_start = br.tell();
+ if !br.read_bool()? {
+ let res = br.read_bool()?;
+ validate!(res);
+ let mut len = br.read(8)? as usize;
+ if len == 255 {
+ len = br.read(24)? as usize;
+ }
+ br.align();
+ validate!(len > 0);
+ let tile_end = tile_start + len * 8;
+ validate!(tile_end > br.tell());
+ validate!(tile_end <= br.tell() + (br.left() as usize));
+ {
+ let mut tile = self.tiles[tile_no].borrow_mut();
+ let ref_tile: Option<Ref<IVITile>>;
+ let mv_scale;
+ if (plane_no == 0) && (band_no == 0) {
+ mv_scale = 0;
+ } else {
+ mv_scale = (((self.bands[0].mb_size >> 3) as i8) - ((band.mb_size >> 3) as i8)) as u8;
+ }
+ if plane_no != 0 || band_no != 0 {
+ let rtile = self.tiles[0].borrow();
+ if (tile.mb_w != rtile.mb_w) || (tile.mb_h != rtile.mb_h) {
+ ref_tile = None;
+ } else {
+ ref_tile = Some(rtile);
+ }
+ } else {
+ ref_tile = None;
+ }
+ dec.decode_mb_info(br, pic_hdr, &band, &mut tile, ref_tile, mv_scale)?;
+ }
+
+ self.decode_tile(br, &band, tile_no, &tr, &tr_dc)?;
+let skip_part = tile_end - br.tell();
+br.skip(skip_part as u32)?;
+ } else {
+ {
+ let mut tile = self.tiles[tile_no].borrow_mut();
+ let ref_tile: Option<Ref<IVITile>>;
+ let mv_scale;
+ if (plane_no == 0) && (band_no == 0) {
+ mv_scale = 0;
+ } else {
+ mv_scale = (((self.bands[0].mb_size >> 3) as i8) - ((band.mb_size >> 3) as i8)) as u8;
+ }
+ if plane_no != 0 || band_no != 0 {
+ let rtile = self.tiles[0].borrow();
+ if (tile.mb_w != rtile.mb_w) || (tile.mb_h != rtile.mb_h) {
+ ref_tile = None;
+ } else {
+ ref_tile = Some(rtile);
+ }
+ } else {
+ ref_tile = None;
+ }
+ let mut mb_idx = 0;
+ for mb_y in 0..tile.mb_h {
+ for mb_x in 0..tile.mb_w {
+ let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size);
+ mb.mtype = MBType::Inter;
+ mb.cbp = 0;
+ if band.inherit_mv {
+ if let Some(ref tileref) = ref_tile {
+ let mx = tileref.mb[mb_idx].mv_x;
+ let my = tileref.mb[mb_idx].mv_y;
+ mb.mv_x = scale_mv(mx, mv_scale);
+ mb.mv_y = scale_mv(my, mv_scale);
+ }
+ }
+ tile.mb[mb_idx] = mb;
+ mb_idx += 1;
+ }
+ }
+ }
+ self.decode_tile(br, &band, tile_no, &tr, &tr_dc)?;
+ }
+ }
+ self.bands[bidx] = band;
+ br.align();
+ Ok(())
+ }
+ fn decode_tile(&mut self, br: &mut BitReader, band: &BandHeader, tile_no: usize, tr: &TrFunc, transform_dc: &TrFuncDC) -> DecoderResult<()> {
+ let mut mb_idx = 0;
+ let mut prev_dc: i32 = 0;
+ let mut tile = self.tiles[tile_no].borrow_mut();
+ let mut frame = self.frames[self.cur_frame].borrow_mut();
+
+ let stride = frame.plane_stride[band.plane_no];
+ let mut dstidx = tile.pos_x + tile.pos_y * stride;
+ let mut dst = &mut frame.plane_buf[band.plane_no];
+ let pos_x = tile.pos_x;
+ let pos_y = tile.pos_y;
+ let tile_w = (tile.w + 15) & !15;
+ let tile_h = (tile.h + 15) & !15;
+ for mb_y in 0..tile.mb_h {
+ for mb_x in 0..tile.mb_w {
+ let mb = &mut tile.mb[mb_idx];
+
+ let is_intra = mb.mtype == MBType::Intra;
+
+ if band.mb_size != band.blk_size {
+ let mut cbp = mb.cbp;
+ for blk_no in 0..4 {
+ let mut blk: [i32; 64] = [0; 64];
+ let boff = (blk_no & 1) * 8 + (blk_no & 2) * 4 * stride + mb_x * 16;
+ if !is_intra {
+ if mb.mtype != MBType::Bidir {
+ let idx;
+ if mb.mtype != MBType::Backward {
+ idx = self.prev_frame;
+ } else {
+ idx = self.next_frame;
+ }
+ let pf = self.frames[idx].borrow();
+ do_mc(&mut dst[dstidx + boff..], stride,
+ &pf.plane_buf[band.plane_no], pf.plane_stride[band.plane_no],
+ pos_x + mb_x * 16 + (blk_no & 1) * 8,
+ pos_y + mb_y * 16 + (blk_no & 2) * 4,
+ pos_x, pos_x + tile_w, pos_y, pos_y + tile_h,
+ mb.mv_x, mb.mv_y, band.halfpel, 8);
+ } else {
+ let pf = self.frames[self.prev_frame].borrow();
+ let nf = self.frames[self.next_frame].borrow();
+ do_mc_b(&mut dst[dstidx + boff..], stride,
+ &pf.plane_buf[band.plane_no], pf.plane_stride[band.plane_no],
+ &nf.plane_buf[band.plane_no], nf.plane_stride[band.plane_no],
+ pos_x + mb_x * 16 + (blk_no & 1) * 8,
+ pos_y + mb_y * 16 + (blk_no & 2) * 4,
+ pos_x, pos_x + tile_w, pos_y, pos_y + tile_h,
+ mb.mv_x, mb.mv_y, mb.mv2_x, mb.mv2_y, band.halfpel,
+ band.blk_size);
+ }
+ }
+ if (cbp & 1) != 0 {
+ if let TxType::Transform8(ref params) = band.ttype {
+ decode_block8x8(br, &band.blk_cb, &band.rvmap, params, is_intra, band.tr.is_2d(), &mut prev_dc, mb.q, &mut blk, tr)?;
+ if is_intra {
+ put_block(&mut dst, dstidx + boff, stride, &blk, 8);
+ } else {
+ add_block(&mut dst, dstidx + boff, stride, &blk, 8);
+ }
+ }
+ } else {
+ if is_intra {
+ (transform_dc)(&mut blk, prev_dc);
+ put_block(&mut dst, dstidx + boff, stride, &blk, 8);
+ }
+ }
+ cbp >>= 1;
+ }
+ } else {
+ let mut blk: [i32; 64] = [0; 64];
+ if !is_intra {
+ if mb.mtype != MBType::Bidir {
+ let idx;
+ if mb.mtype != MBType::Backward {
+ idx = self.prev_frame;
+ } else {
+ idx = self.next_frame;
+ }
+ let pf = self.frames[idx].borrow();
+ do_mc(&mut dst[dstidx + mb_x * band.blk_size..], stride,
+ &pf.plane_buf[band.plane_no], pf.plane_stride[band.plane_no],
+ pos_x + mb_x * band.mb_size,
+ pos_y + mb_y * band.mb_size,
+ pos_x, pos_x + tile_w, pos_y, pos_y + tile_h,
+ mb.mv_x, mb.mv_y, band.halfpel, band.blk_size);
+ } else {
+ let pf = self.frames[self.prev_frame].borrow();
+ let nf = self.frames[self.next_frame].borrow();
+ do_mc_b(&mut dst[dstidx + mb_x * band.blk_size..], stride,
+ &pf.plane_buf[band.plane_no], pf.plane_stride[band.plane_no],
+ &nf.plane_buf[band.plane_no], nf.plane_stride[band.plane_no],
+ pos_x + mb_x * band.mb_size,
+ pos_y + mb_y * band.mb_size,
+ pos_x, pos_x + tile_w, pos_y, pos_y + tile_h,
+ mb.mv_x, mb.mv_y, mb.mv2_x, mb.mv2_y, band.halfpel,
+ band.blk_size);
+ }
+ }
+ if mb.cbp != 0 {
+ if let TxType::Transform8(ref params) = band.ttype {
+ decode_block8x8(br, &band.blk_cb, &band.rvmap, params, is_intra, band.tr.is_2d(), &mut prev_dc, mb.q, &mut blk, tr)?;
+ }
+ if let TxType::Transform4(ref params) = band.ttype {
+ decode_block4x4(br, &band.blk_cb, &band.rvmap, params, is_intra, band.tr.is_2d(), &mut prev_dc, mb.q, &mut blk, tr)?;
+ }
+ if is_intra {
+ put_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, band.blk_size);
+ } else {
+ add_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, band.blk_size);
+ }
+ } else {
+ if is_intra {
+ (transform_dc)(&mut blk, prev_dc);
+ put_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, band.blk_size);
+ }
+ }
+ }
+ mb_idx += 1;
+ }
+ dstidx += stride * band.mb_size;
+ }
+ br.align();
+ Ok(())
+ }
+
+ fn find_unused_frame(&self) -> usize {
+ for fno in 0..4 {
+ if (fno != self.iref_0) && (fno != self.iref_1) && (fno != self.scal_ref) {
+ return fno;
+ }
+ }
+ unreachable!();
+ }
+
+ fn decode_single_frame<'a>(&mut self, dec: &mut IndeoXParser, br: &mut BitReader<'a>) -> DecoderResult<NABufferType> {
+ let pic_hdr = dec.decode_picture_header(br)?;
+ self.ftype = pic_hdr.ftype;
+ if pic_hdr.ftype.is_null() {
+ return Ok(NABufferType::None);
+ }
+
+ self.cur_frame = self.find_unused_frame();
+ match self.ftype {
+ IVIFrameType::Inter => {
+ self.prev_frame = self.iref_0;
+ if self.prev_frame == MISSING_REF {
+ return Err(DecoderError::MissingReference);
+ }
+ },
+ IVIFrameType::InterDroppable => {
+ self.prev_frame = self.scal_ref;
+ if self.prev_frame == MISSING_REF {
+ return Err(DecoderError::MissingReference);
+ }
+ },
+ IVIFrameType::InterScal => {
+ self.prev_frame = self.scal_ref;
+ if self.prev_frame == MISSING_REF {
+ return Err(DecoderError::MissingReference);
+ }
+ },
+ IVIFrameType::Bidir => {
+ self.prev_frame = self.iref_1;
+ self.next_frame = self.iref_0;
+ if (self.prev_frame == MISSING_REF) || (self.next_frame == MISSING_REF) {
+ return Err(DecoderError::MissingReference);
+ }
+ },
+ _ => {},
+ };
+
+ let mut vinfo;
+ if pic_hdr.transparent {
+ vinfo = self.vinfoa.clone();
+ } else {
+ vinfo = self.vinfo.clone();
+ }
+ vinfo.set_width(pic_hdr.width);
+ vinfo.set_height(pic_hdr.height);
+ let mut buftype = alloc_video_buffer(vinfo, 0)?;
+ self.realloc(&pic_hdr)?;
+ self.frames[self.cur_frame].borrow_mut().realloc(&pic_hdr)?;
+
+ for plane in 0..3 {
+ let num_bands = if plane == 0 { pic_hdr.luma_bands } else { pic_hdr.chroma_bands };
+ for band in 0..num_bands {
+ self.decode_band(&pic_hdr, dec, br, plane, band)?;
+ }
+ if let NABufferType::Video(ref mut vb) = buftype {
+ let mut frame = self.frames[self.cur_frame].borrow_mut();
+ if num_bands == 1 {
+ frame.fill_plane(vb, plane);
+ } else {
+ let (w, h) = vb.get_dimensions(plane);
+ let dstride = vb.get_stride(plane);
+ let off = vb.get_offset(plane);
+ let mut dst = vb.get_data_mut();
+ dec.recombine_plane(&frame.plane_buf[plane], frame.plane_stride[plane], &mut dst[off..], dstride, w, h);
+ }
+ }
+ }
+ if pic_hdr.transparent {
+ let mut frame = self.frames[self.cur_frame].borrow_mut();
+ let stride = frame.plane_stride[3];
+ read_trans_band_header(br, pic_hdr.width, pic_hdr.height, &mut frame.plane_buf[3], stride)?;
+ if let NABufferType::Video(ref mut vb) = buftype {
+ frame.fill_plane(vb, 3);
+ }
+ }
+
+ match self.ftype {
+ IVIFrameType::Intra | IVIFrameType::Inter => {
+ self.iref_1 = self.iref_0;
+ self.iref_0 = self.cur_frame;
+ self.scal_ref = self.cur_frame;
+ },
+ IVIFrameType::InterScal => {
+ self.scal_ref = self.cur_frame;
+ },
+ _ => {},
+ };
+
+ Ok(buftype)
+ }
+
+ pub fn decode_frame<'a>(&mut self, dec: &mut IndeoXParser, br: &mut BitReader<'a>) -> DecoderResult<NABufferType> {
+ let res = self.decode_single_frame(dec, br);
+ if res.is_err() { return res; }
+ if (self.ftype == IVIFrameType::Intra) && (br.left() > 16) {
+ loop {
+ if br.left() < 8 { break; }
+ if br.read(8)? == 0 { break; }
+ }
+ loop {
+ if br.left() < 8 { break; }
+ if br.peek(8) != 0 { break; }
+ br.skip(8)?;
+ }
+ if br.left() > 24 {
+ let seq = br.peek(21);
+ if seq == 0xBFFF8 {
+ let res2 = self.decode_single_frame(dec, br);
+ if res2.is_ok() {
+ self.bref = Some(res2.unwrap());
+ }
+ }
+ self.ftype = IVIFrameType::Intra;
+ }
+ }
+ if let Ok(NABufferType::None) = res {
+ if self.bref.is_some() {
+ let mut bref: Option<NABufferType> = None;
+ mem::swap(&mut bref, &mut self.bref);
+ self.ftype = IVIFrameType::Inter;
+ return Ok(bref.unwrap());
+ }
+ }
+ res
+ }
+
+ pub fn is_intra(&mut self) -> bool {
+ self.ftype.is_intra()
+ }
+ pub fn get_frame_type(&mut self) -> FrameType {
+ match self.ftype {
+ IVIFrameType::Intra => { FrameType::I },
+ IVIFrameType::Intra1 => { FrameType::I },
+ IVIFrameType::Inter => { FrameType::P },
+ IVIFrameType::InterDroppable => { FrameType::P },
+ IVIFrameType::InterScal => { FrameType::P },
+ IVIFrameType::Bidir => { FrameType::B },
+ _ => { FrameType::Skip },
+ }
+ }
+}
+
+pub struct RVMap {
+ pub eob_sym: u32,
+ pub esc_sym: u32,
+ pub runtab: [u8; 256],
+ pub valtab: [i8; 256],
+}
+
+impl Clone for RVMap {
+ fn clone(&self) -> RVMap {
+ let mut runtab: [u8; 256] = [0; 256];
+ let mut valtab: [i8; 256] = [0; 256];
+ runtab.copy_from_slice(&self.runtab);
+ valtab.copy_from_slice(&self.valtab);
+ RVMap { eob_sym: self.eob_sym, esc_sym: self.esc_sym, runtab: runtab, valtab: valtab }
+ }
+}
+
+pub const IVI_ZERO_RVMAP: RVMap = RVMap { eob_sym: 0, esc_sym: 0, runtab: [0; 256], valtab: [0; 256] };
+
+pub static IVI_RVMAPS: [RVMap; 9] = [
+ RVMap { eob_sym: 5, esc_sym: 2, runtab: [
+ 1, 1, 0, 1, 1, 0, 1, 1, 2, 2, 1, 1, 1, 1, 3, 3,
+ 1, 1, 2, 2, 1, 1, 4, 4, 1, 1, 1, 1, 2, 2, 5, 5,
+ 1, 1, 3, 3, 1, 1, 6, 6, 1, 2, 1, 2, 7, 7, 1, 1,
+ 8, 8, 1, 1, 4, 2, 1, 4, 2, 1, 3, 3, 1, 1, 1, 9,
+ 9, 1, 2, 1, 2, 1, 5, 5, 1, 1, 10, 10, 1, 1, 3, 3,
+ 2, 2, 1, 1, 11, 11, 6, 4, 4, 1, 6, 1, 2, 1, 2, 12,
+ 8, 1, 12, 7, 8, 7, 1, 16, 1, 16, 1, 3, 3, 13, 1, 13,
+ 2, 2, 1, 15, 1, 5, 14, 15, 1, 5, 14, 1, 17, 8, 17, 8,
+ 1, 4, 4, 2, 2, 1, 25, 25, 24, 24, 1, 3, 1, 3, 1, 8,
+ 6, 7, 6, 1, 18, 8, 18, 1, 7, 23, 2, 2, 23, 1, 1, 21,
+ 22, 9, 9, 22, 19, 1, 21, 5, 19, 5, 1, 33, 20, 33, 20, 8,
+ 4, 4, 1, 32, 2, 2, 8, 3, 32, 26, 3, 1, 7, 7, 26, 6,
+ 1, 6, 1, 1, 16, 1, 10, 1, 10, 2, 16, 29, 28, 2, 29, 28,
+ 1, 27, 5, 8, 5, 27, 1, 8, 3, 7, 3, 31, 41, 31, 1, 41,
+ 6, 1, 6, 7, 4, 4, 1, 1, 2, 1, 2, 11, 34, 30, 11, 1,
+ 30, 15, 15, 34, 36, 40, 36, 40, 35, 35, 37, 37, 39, 39, 38, 38 ],
+ valtab: [
+ 1, -1, 0, 2, -2, 0, 3, -3, 1, -1, 4, -4, 5, -5, 1, -1,
+ 6, -6, 2, -2, 7, -7, 1, -1, 8, -8, 9, -9, 3, -3, 1, -1,
+ 10, -10, 2, -2, 11, -11, 1, -1, 12, 4, -12, -4, 1, -1, 13, -13,
+ 1, -1, 14, -14, 2, 5, 15, -2, -5, -15, -3, 3, 16, -16, 17, 1,
+ -1, -17, 6, 18, -6, -18, 2, -2, 19, -19, 1, -1, 20, -20, 4, -4,
+ 7, -7, 21, -21, 1, -1, 2, 3, -3, 22, -2, -22, 8, 23, -8, 1,
+ 2, -23, -1, 2, -2, -2, 24, 1, -24, -1, 25, 5, -5, 1, -25, -1,
+ 9, -9, 26, 1, -26, 3, 1, -1, 27, -3, -1, -27, 1, 3, -1, -3,
+ 28, -4, 4, 10, -10, -28, 1, -1, 1, -1, 29, 6, -29, -6, 30, -4,
+ 3, 3, -3, -30, 1, 4, -1, 31, -3, 1, 11, -11, -1, -31, 32, -1,
+ -1, 2, -2, 1, 1, -32, 1, 4, -1, -4, 33, -1, 1, 1, -1, 5,
+ 5, -5, -33, -1, -12, 12, -5, -7, 1, 1, 7, 34, 4, -4, -1, 4,
+ -34, -4, 35, 36, -2, -35, -2, -36, 2, 13, 2, -1, 1, -13, 1, -1,
+ 37, 1, -5, 6, 5, -1, 38, -6, -8, 5, 8, -1, 1, 1, -37, -1,
+ 5, 39, -5, -5, 6, -6, -38, -39, -14, 40, 14, 2, 1, 1, -2, -40,
+ -1, -2, 2, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1 ],
+ },
+ RVMap { eob_sym: 0, esc_sym: 38, runtab: [
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8, 6, 8, 7,
+ 7, 9, 9, 10, 10, 11, 11, 1, 12, 1, 12, 13, 13, 16, 14, 16,
+ 14, 15, 15, 17, 17, 18, 0, 18, 19, 20, 21, 19, 22, 21, 20, 22,
+ 25, 24, 2, 25, 24, 23, 23, 2, 26, 28, 26, 28, 29, 27, 29, 27,
+ 33, 33, 1, 32, 1, 3, 32, 30, 36, 3, 36, 30, 31, 31, 35, 34,
+ 37, 41, 34, 35, 37, 4, 41, 4, 49, 8, 8, 49, 40, 38, 5, 38,
+ 40, 39, 5, 39, 42, 43, 42, 7, 57, 6, 43, 44, 6, 50, 7, 44,
+ 57, 48, 50, 48, 45, 45, 46, 47, 51, 46, 47, 58, 1, 51, 58, 1,
+ 52, 59, 53, 9, 52, 55, 55, 59, 53, 56, 54, 56, 54, 9, 64, 64,
+ 60, 63, 60, 63, 61, 62, 61, 62, 2, 10, 2, 10, 11, 1, 11, 13,
+ 12, 1, 12, 13, 16, 16, 8, 8, 14, 3, 3, 15, 14, 15, 4, 4,
+ 1, 17, 17, 5, 1, 7, 7, 5, 6, 1, 2, 2, 6, 22, 1, 25,
+ 21, 22, 8, 24, 1, 21, 25, 24, 8, 18, 18, 23, 9, 20, 23, 33,
+ 29, 33, 20, 1, 19, 1, 29, 36, 9, 36, 19, 41, 28, 57, 32, 3,
+ 28, 3, 1, 27, 49, 49, 1, 32, 26, 26, 2, 4, 4, 7, 57, 41,
+ 2, 7, 10, 5, 37, 16, 10, 27, 8, 8, 13, 16, 37, 13, 1, 5 ],
+ valtab: [
+ 0, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1,
+ -1, 1, -1, 1, -1, 1, -1, 2, 1, -2, -1, 1, -1, 1, 1, -1,
+ -1, 1, -1, 1, -1, 1, 0, -1, 1, 1, 1, -1, 1, -1, -1, -1,
+ 1, 1, 2, -1, -1, 1, -1, -2, 1, 1, -1, -1, 1, 1, -1, -1,
+ 1, -1, 3, 1, -3, 2, -1, 1, 1, -2, -1, -1, -1, 1, 1, 1,
+ 1, 1, -1, -1, -1, 2, -1, -2, 1, 2, -2, -1, 1, 1, 2, -1,
+ -1, 1, -2, -1, 1, 1, -1, 2, 1, 2, -1, 1, -2, -1, -2, -1,
+ -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 4, -1, -1, -4,
+ 1, 1, 1, 2, -1, -1, 1, -1, -1, 1, -1, -1, 1, -2, 1, -1,
+ 1, 1, -1, -1, 1, 1, -1, -1, 3, 2, -3, -2, 2, 5, -2, 2,
+ 2, -5, -2, -2, -2, 2, -3, 3, 2, 3, -3, 2, -2, -2, 3, -3,
+ 6, 2, -2, 3, -6, 3, -3, -3, 3, 7, -4, 4, -3, 2, -7, 2,
+ 2, -2, -4, 2, 8, -2, -2, -2, 4, 2, -2, 2, 3, 2, -2, -2,
+ 2, 2, -2, -8, -2, 9, -2, 2, -3, -2, 2, -2, 2, 2, 2, 4,
+ -2, -4, 10, 2, 2, -2, -9, -2, 2, -2, 5, 4, -4, 4, -2, 2,
+ -5, -4, -3, 4, 2, -3, 3, -2, -5, 5, 3, 3, -2, -3, -10, -4 ],
+ },
+ RVMap { eob_sym: 2, esc_sym: 11, runtab: [
+ 1, 1, 0, 2, 2, 1, 1, 3, 3, 4, 4, 0, 1, 1, 5, 5,
+ 2, 2, 6, 6, 7, 7, 1, 8, 1, 8, 3, 3, 9, 9, 1, 2,
+ 2, 1, 4, 10, 4, 10, 11, 11, 1, 5, 12, 12, 1, 5, 13, 13,
+ 3, 3, 6, 6, 2, 2, 14, 14, 16, 16, 15, 7, 15, 8, 8, 7,
+ 1, 1, 17, 17, 4, 4, 1, 1, 18, 18, 2, 2, 5, 5, 25, 3,
+ 9, 3, 25, 9, 19, 24, 19, 24, 1, 21, 20, 1, 21, 22, 20, 22,
+ 23, 23, 8, 6, 33, 6, 8, 33, 7, 7, 26, 26, 1, 32, 1, 32,
+ 28, 4, 28, 10, 29, 27, 27, 10, 41, 4, 29, 2, 2, 41, 36, 31,
+ 49, 31, 34, 30, 34, 36, 30, 35, 1, 49, 11, 5, 35, 11, 1, 3,
+ 3, 5, 37, 37, 8, 40, 8, 40, 12, 12, 42, 42, 1, 38, 16, 57,
+ 1, 6, 16, 39, 38, 6, 7, 7, 13, 13, 39, 43, 2, 43, 57, 2,
+ 50, 9, 44, 9, 50, 4, 15, 48, 44, 4, 1, 15, 48, 14, 14, 1,
+ 45, 45, 8, 3, 5, 8, 51, 47, 3, 46, 46, 47, 5, 51, 1, 17,
+ 17, 58, 1, 58, 2, 52, 52, 2, 53, 7, 59, 6, 6, 56, 53, 55,
+ 7, 55, 1, 54, 59, 56, 54, 10, 1, 10, 4, 60, 1, 60, 8, 4,
+ 8, 64, 64, 61, 1, 63, 3, 63, 62, 61, 5, 11, 5, 3, 11, 62 ],
+ valtab: [
+ 1, -1, 0, 1, -1, 2, -2, 1, -1, 1, -1, 0, 3, -3, 1, -1,
+ 2, -2, 1, -1, 1, -1, 4, 1, -4, -1, 2, -2, 1, -1, 5, 3,
+ -3, -5, 2, 1, -2, -1, 1, -1, 6, 2, 1, -1, -6, -2, 1, -1,
+ 3, -3, 2, -2, 4, -4, 1, -1, 1, -1, 1, 2, -1, 2, -2, -2,
+ 7, -7, 1, -1, 3, -3, 8, -8, 1, -1, 5, -5, 3, -3, 1, 4,
+ 2, -4, -1, -2, 1, 1, -1, -1, 9, 1, 1, -9, -1, 1, -1, -1,
+ 1, -1, 3, -3, 1, 3, -3, -1, 3, -3, 1, -1, 10, 1, -10, -1,
+ 1, 4, -1, 2, 1, -1, 1, -2, 1, -4, -1, 6, -6, -1, 1, 1,
+ 1, -1, 1, 1, -1, -1, -1, 1, 11, -1, -2, 4, -1, 2, -11, 5,
+ -5, -4, -1, 1, 4, 1, -4, -1, -2, 2, 1, -1, 12, 1, -2, 1,
+ -12, 4, 2, 1, -1, -4, 4, -4, 2, -2, -1, 1, 7, -1, -1, -7,
+ -1, -3, 1, 3, 1, 5, 2, 1, -1, -5, 13, -2, -1, 2, -2, -13,
+ 1, -1, 5, 6, 5, -5, 1, 1, -6, 1, -1, -1, -5, -1, 14, 2,
+ -2, 1, -14, -1, 8, 1, -1, -8, 1, 5, 1, 5, -5, 1, -1, 1,
+ -5, -1, 15, 1, -1, -1, -1, 3, -15, -3, 6, 1, 16, -1, 6, -6,
+ -6, 1, -1, 1, -16, 1, 7, -1, 1, -1, -6, -3, 6, -7, 3, -1 ]
+ },
+ RVMap { eob_sym: 0, esc_sym: 35, runtab: [
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6, 6, 7,
+ 7, 8, 8, 9, 9, 2, 2, 10, 10, 1, 1, 11, 11, 12, 12, 3,
+ 3, 13, 13, 0, 14, 14, 16, 15, 16, 15, 4, 4, 17, 1, 17, 1,
+ 5, 5, 18, 18, 2, 2, 6, 6, 8, 19, 7, 8, 7, 19, 20, 20,
+ 21, 21, 22, 24, 22, 24, 23, 23, 1, 1, 25, 25, 3, 3, 26, 26,
+ 9, 9, 27, 27, 28, 28, 33, 29, 4, 33, 29, 1, 4, 1, 32, 32,
+ 2, 2, 31, 10, 30, 10, 30, 31, 34, 34, 5, 5, 36, 36, 35, 41,
+ 35, 11, 41, 11, 37, 1, 8, 8, 37, 6, 1, 6, 40, 7, 7, 40,
+ 12, 38, 12, 39, 39, 38, 49, 13, 49, 13, 3, 42, 3, 42, 16, 16,
+ 43, 43, 14, 14, 1, 1, 44, 15, 44, 15, 2, 2, 57, 48, 50, 48,
+ 57, 50, 4, 45, 45, 4, 46, 47, 47, 46, 1, 51, 1, 17, 17, 51,
+ 8, 9, 9, 5, 58, 8, 58, 5, 52, 52, 55, 56, 53, 56, 55, 59,
+ 59, 53, 54, 1, 6, 54, 7, 7, 6, 1, 2, 3, 2, 3, 64, 60,
+ 60, 10, 10, 64, 61, 62, 61, 63, 1, 63, 62, 1, 18, 24, 18, 4,
+ 25, 4, 8, 21, 21, 1, 24, 22, 25, 22, 8, 11, 19, 11, 23, 1,
+ 20, 23, 19, 20, 5, 12, 5, 1, 16, 2, 12, 13, 2, 13, 1, 16 ],
+ valtab: [
+ 0, 1, -1, 1, -1, 1, -1, 1, -1, 2, -2, 1, -1, 1, -1, 1,
+ -1, 1, -1, 1, -1, 2, -2, 1, -1, 3, -3, 1, -1, 1, -1, 2,
+ -2, 1, -1, 0, 1, -1, 1, 1, -1, -1, 2, -2, 1, 4, -1, -4,
+ 2, -2, 1, -1, -3, 3, 2, -2, 2, 1, 2, -2, -2, -1, 1, -1,
+ 1, -1, 1, 1, -1, -1, 1, -1, 5, -5, 1, -1, 3, -3, 1, -1,
+ 2, -2, 1, -1, 1, -1, 1, 1, 3, -1, -1, 6, -3, -6, -1, 1,
+ 4, -4, 1, 2, 1, -2, -1, -1, 1, -1, 3, -3, 1, -1, 1, 1,
+ -1, 2, -1, -2, 1, 7, -3, 3, -1, 3, -7, -3, 1, -3, 3, -1,
+ 2, 1, -2, 1, -1, -1, 1, 2, -1, -2, -4, -1, 4, 1, 2, -2,
+ 1, -1, -2, 2, 8, -8, -1, 2, 1, -2, -5, 5, 1, -1, -1, 1,
+ -1, 1, 4, -1, 1, -4, -1, -1, 1, 1, 9, 1, -9, 2, -2, -1,
+ -4, 3, -3, -4, -1, 4, 1, 4, 1, -1, 1, -1, 1, 1, -1, 1,
+ -1, -1, -1, 10, 4, 1, 4, -4, -4, -10, 6, 5, -6, -5, 1, -1,
+ 1, 3, -3, -1, 1, -1, -1, -1, 11, 1, 1, -11, -2, -2, 2, 5,
+ -2, -5, -5, 2, -2, 12, 2, -2, 2, 2, 5, -3, -2, 3, -2, -12,
+ -2, 2, 2, 2, -5, 3, 5, 13, -3, 7, -3, -3, -7, 3, -13, 3 ]
+ },
+ RVMap { eob_sym: 0, esc_sym: 34, runtab: [
+ 0, 1, 1, 1, 2, 2, 1, 3, 3, 1, 1, 1, 4, 4, 1, 5,
+ 2, 1, 5, 2, 1, 1, 6, 6, 1, 1, 1, 1, 1, 7, 3, 1,
+ 2, 3, 0, 1, 2, 7, 1, 1, 1, 8, 1, 1, 8, 1, 1, 1,
+ 9, 1, 9, 1, 2, 1, 1, 2, 1, 1, 10, 4, 1, 10, 1, 4,
+ 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 2, 1, 5, 1, 1, 1,
+ 2, 5, 1, 11, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 1, 6, 1, 6, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 12,
+ 3, 1, 12, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1,
+ 4, 1, 1, 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 5,
+ 1, 1, 1, 1, 1, 7, 1, 7, 1, 1, 2, 3, 1, 1, 1, 1,
+ 5, 1, 1, 1, 1, 1, 1, 2, 13, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 13, 2, 1, 1, 4, 1, 1, 1,
+ 3, 1, 6, 1, 1, 1, 14, 1, 1, 1, 1, 1, 14, 6, 1, 1,
+ 1, 1, 15, 2, 4, 1, 2, 3, 15, 1, 1, 1, 8, 1, 1, 8,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1 ],
+ valtab: [
+ 0, 1, -1, 2, 1, -1, -2, 1, -1, 3, -3, 4, 1, -1, -4, 1,
+ 2, 5, -1, -2, -5, 6, 1, -1, -6, 7, -7, 8, -8, 1, 2, 9,
+ 3, -2, 0, -9, -3, -1, 10, -10, 11, 1, -11, 12, -1, -12, 13, -13,
+ 1, 14, -1, -14, 4, 15, -15, -4, 16, -16, 1, 2, 17, -1, -17, -2,
+ 18, -18, 19, -19, 20, 3, -20, 21, -21, -3, 5, 22, 2, -22, -23, 23,
+ -5, -2, 24, 1, -24, -1, 25, -25, 26, -26, -27, 27, 28, 29, -28, -29,
+ 6, 30, 2, -31, -2, -30, 31, -6, -32, 32, 33, -33, 34, -35, -34, 1,
+ 4, -36, -1, 35, 37, 36, 7, -37, 38, -4, -38, 39, 41, 40, -40, -39,
+ 3, 42, -43, -41, -7, -42, 43, -3, 44, -44, 45, -45, 46, 47, 8, -47,
+ -48, -46, 50, -50, 48, 49, 51, -49, 52, -52, 5, -51, -8, -53, 53, 3,
+ -56, 56, 55, 54, -54, 2, 60, -2, -55, 58, 9, -5, 59, 57, -57, -63,
+ -3, -58, -60, -61, 61, -59, -62, -9, 1, 64, 62, 69, -64, 63, 65, -67,
+ -68, 66, -65, 68, -66, -69, 67, -70, -1, 10, 71, -71, 4, 73, 72, 70,
+ 6, -76, -3, 74, -78, -74, 1, 78, 80, -72, -75, 76, -1, 3, -73, 79,
+ 75, 77, 1, 11, -4, -79, -10, -6, -1, -77, -83, -80, 2, 81, -84, -2,
+ 83, -81, 82, -82, 84, -87, -86, 85, -11, -85, 86, -89, 87, -88, 88, 89 ]
+ },
+ RVMap { eob_sym: 2, esc_sym: 33, runtab: [
+ 1, 1, 0, 2, 1, 2, 1, 3, 3, 1, 1, 4, 4, 2, 2, 1,
+ 1, 5, 5, 6, 1, 6, 1, 7, 7, 3, 3, 2, 8, 2, 8, 1,
+ 1, 0, 9, 9, 1, 1, 10, 4, 10, 4, 11, 11, 2, 1, 2, 1,
+ 12, 12, 3, 3, 1, 1, 13, 5, 5, 13, 14, 1, 1, 14, 2, 2,
+ 6, 6, 15, 1, 1, 15, 16, 4, 7, 16, 4, 7, 1, 1, 3, 3,
+ 8, 8, 2, 2, 1, 1, 17, 17, 1, 1, 18, 18, 5, 5, 2, 2,
+ 1, 1, 9, 19, 9, 19, 20, 3, 3, 20, 1, 10, 21, 1, 10, 4,
+ 4, 21, 22, 6, 6, 22, 1, 1, 23, 24, 2, 2, 23, 24, 11, 1,
+ 1, 11, 7, 25, 7, 1, 1, 25, 8, 8, 3, 26, 3, 1, 12, 2,
+ 2, 26, 1, 12, 5, 5, 27, 4, 1, 4, 1, 27, 28, 1, 28, 13,
+ 1, 13, 2, 29, 2, 1, 32, 6, 1, 30, 14, 29, 14, 6, 3, 31,
+ 3, 1, 30, 1, 32, 31, 33, 9, 33, 1, 1, 7, 9, 7, 2, 2,
+ 1, 1, 4, 36, 34, 4, 5, 10, 10, 5, 34, 1, 1, 35, 8, 8,
+ 36, 3, 35, 1, 15, 3, 2, 1, 16, 15, 16, 2, 37, 1, 37, 1,
+ 1, 1, 6, 6, 38, 1, 38, 11, 1, 39, 39, 40, 11, 2, 41, 4,
+ 40, 1, 2, 4, 1, 1, 1, 41, 3, 1, 3, 1, 5, 7, 5, 7 ],
+ valtab: [
+ 1, -1, 0, 1, 2, -1, -2, 1, -1, 3, -3, 1, -1, 2, -2, 4,
+ -4, 1, -1, 1, 5, -1, -5, 1, -1, 2, -2, 3, 1, -3, -1, 6,
+ -6, 0, 1, -1, 7, -7, 1, 2, -1, -2, 1, -1, 4, 8, -4, -8,
+ 1, -1, 3, -3, 9, -9, 1, 2, -2, -1, 1, 10, -10, -1, 5, -5,
+ 2, -2, 1, 11, -11, -1, 1, 3, 2, -1, -3, -2, 12, -12, 4, -4,
+ 2, -2, -6, 6, 13, -13, 1, -1, 14, -14, 1, -1, 3, -3, 7, -7,
+ 15, -15, 2, 1, -2, -1, 1, 5, -5, -1, -16, 2, 1, 16, -2, 4,
+ -4, -1, 1, 3, -3, -1, 17, -17, 1, 1, -8, 8, -1, -1, 2, 18,
+ -18, -2, 3, 1, -3, 19, -19, -1, 3, -3, 6, 1, -6, 20, 2, 9,
+ -9, -1, -20, -2, 4, -4, 1, -5, 21, 5, -21, -1, 1, -22, -1, 2,
+ 22, -2, 10, 1, -10, 23, 1, 4, -23, 1, 2, -1, -2, -4, -7, 1,
+ 7, -24, -1, 24, -1, -1, 1, 3, -1, -25, 25, 4, -3, -4, 11, -11,
+ 26, -26, 6, 1, 1, -6, -5, -3, 3, 5, -1, -27, 27, 1, 4, -4,
+ -1, -8, -1, 28, 2, 8, -12, -28, -2, -2, 2, 12, -1, 29, 1, -29,
+ 30, -30, 5, -5, 1, -31, -1, 3, 31, -1, 1, 1, -3, -13, 1, -7,
+ -1, -32, 13, 7, 32, 33, -33, -1, -9, -34, 9, 34, -6, 5, 6, -5 ]
+ },
+ RVMap { eob_sym: 2, esc_sym: 13, runtab: [
+ 1, 1, 0, 1, 1, 2, 2, 1, 1, 3, 3, 1, 1, 0, 2, 2,
+ 4, 1, 4, 1, 1, 1, 5, 5, 1, 1, 6, 6, 2, 2, 1, 1,
+ 3, 3, 7, 7, 1, 1, 8, 8, 1, 1, 2, 2, 1, 9, 1, 9,
+ 4, 4, 10, 1, 1, 10, 1, 1, 11, 11, 3, 3, 1, 2, 1, 2,
+ 1, 1, 12, 12, 5, 5, 1, 1, 13, 1, 1, 13, 2, 2, 1, 1,
+ 6, 6, 1, 1, 4, 14, 4, 14, 3, 1, 3, 1, 1, 1, 15, 7,
+ 15, 2, 2, 7, 1, 1, 1, 8, 1, 8, 16, 16, 1, 1, 1, 1,
+ 2, 1, 1, 2, 1, 1, 3, 5, 5, 3, 4, 1, 1, 4, 1, 1,
+ 17, 17, 9, 1, 1, 9, 2, 2, 1, 1, 10, 10, 1, 6, 1, 1,
+ 6, 18, 1, 1, 18, 1, 1, 1, 2, 2, 3, 1, 3, 1, 1, 1,
+ 4, 1, 19, 1, 19, 7, 1, 1, 20, 1, 4, 20, 1, 7, 11, 2,
+ 1, 11, 21, 2, 8, 5, 1, 8, 1, 5, 21, 1, 1, 1, 22, 1,
+ 1, 22, 1, 1, 3, 3, 1, 23, 2, 12, 24, 1, 1, 2, 1, 1,
+ 12, 23, 1, 1, 24, 1, 1, 1, 4, 1, 1, 1, 2, 1, 6, 6,
+ 4, 2, 1, 1, 1, 1, 1, 1, 1, 14, 13, 3, 1, 25, 9, 25,
+ 14, 1, 9, 3, 13, 1, 1, 1, 1, 1, 10, 1, 1, 2, 10, 2 ],
+ valtab: [
+ -20, -1, 0, 2, -2, 1, -1, 3, -3, 1, -1, 4, -4, 0, 2, -2,
+ 1, 5, -1, -5, 6, -6, 1, -1, 7, -7, 1, -1, 3, -3, 8, -8,
+ 2, -2, 1, -1, 9, -9, 1, -1, 10, -10, 4, -4, 11, 1, -11, -1,
+ 2, -2, 1, 12, -12, -1, 13, -13, 1, -1, 3, -3, 14, 5, -14, -5,
+ -15, 15, -1, 1, 2, -2, 16, -16, 1, 17, -17, -1, 6, -6, 18, -18,
+ 2, -2, -19, 19, -3, 1, 3, -1, 4, 20, -4, 1, -21, 21, 1, 2,
+ -1, -7, 7, -2, 22, -22, 23, 2, -23, -2, 1, -1, -24, 24, -25, 25,
+ -8, -26, 26, 8, -27, 27, 5, 3, -3, -5, -4, 28, -28, 4, 29, -29,
+ 1, -1, -2, -30, 30, 2, 9, -9, -31, 31, 2, -2, -32, 3, 32, -33,
+ -3, 1, 33, -34, -1, 34, -35, 35, -10, 10, -6, 36, 6, -36, 37, -37,
+ -5, 38, 1, -38, -1, 3, 39, -39, -1, 40, 5, 1, -40, -3, 2, -11,
+ -41, -2, 1, 11, -3, -4, 41, 3, 42, 4, -1, -43, -42, 43, 1, -44,
+ 45, -1, 44, -45, -7, 7, -46, 1, -12, 2, 1, -47, 46, 12, 47, 48,
+ -2, -1, -48, 49, -1, -50, -49, 50, -6, -51, 51, 52, -13, 53, -4, 4,
+ 6, 13, -53, -52, -54, 55, 54, -55, -56, -2, 2, -8, 56, 1, -3, -1,
+ 2, 58, 3, 8, -2, 57, -58, -60, -59, -57, -3, 60, 59, -14, 3, 14 ]
+ },
+ RVMap { eob_sym: 2, esc_sym: 38, runtab: [
+ 1, 1, 0, 2, 2, 1, 1, 3, 3, 4, 4, 5, 5, 1, 1, 6,
+ 6, 2, 2, 7, 7, 8, 8, 1, 1, 3, 3, 9, 9, 10, 10, 1,
+ 1, 2, 2, 4, 4, 11, 0, 11, 12, 12, 13, 13, 1, 1, 5, 5,
+ 14, 14, 15, 16, 15, 16, 3, 3, 1, 6, 1, 6, 2, 2, 7, 7,
+ 8, 8, 17, 17, 1, 1, 4, 4, 18, 18, 2, 2, 1, 19, 1, 20,
+ 19, 20, 21, 21, 3, 3, 22, 22, 5, 5, 24, 1, 1, 23, 9, 23,
+ 24, 9, 2, 2, 10, 1, 1, 10, 6, 6, 25, 4, 4, 25, 7, 7,
+ 26, 8, 1, 8, 3, 1, 26, 3, 11, 11, 27, 27, 2, 28, 1, 2,
+ 28, 1, 12, 12, 5, 5, 29, 13, 13, 29, 32, 1, 1, 33, 31, 30,
+ 32, 4, 30, 33, 4, 31, 3, 14, 1, 1, 3, 34, 34, 2, 2, 14,
+ 6, 6, 35, 36, 35, 36, 1, 15, 1, 16, 16, 15, 7, 9, 7, 9,
+ 37, 8, 8, 37, 1, 1, 39, 2, 38, 39, 2, 40, 5, 38, 40, 5,
+ 3, 3, 4, 4, 10, 10, 1, 1, 1, 1, 41, 2, 41, 2, 6, 6,
+ 1, 1, 11, 42, 11, 43, 3, 42, 3, 17, 4, 43, 1, 17, 7, 1,
+ 8, 44, 4, 7, 44, 5, 8, 2, 5, 1, 2, 48, 45, 1, 12, 45,
+ 12, 48, 13, 13, 1, 9, 9, 46, 1, 46, 47, 47, 49, 18, 18, 49 ],
+ valtab: [
+ 1, -1, 0, 1, -1, 2, -2, 1, -1, 1, -1, 1, -1, 3, -3, 1,
+ -1, -2, 2, 1, -1, 1, -1, 4, -4, -2, 2, 1, -1, 1, -1, 5,
+ -5, -3, 3, 2, -2, 1, 0, -1, 1, -1, 1, -1, 6, -6, 2, -2,
+ 1, -1, 1, 1, -1, -1, -3, 3, 7, 2, -7, -2, -4, 4, 2, -2,
+ 2, -2, 1, -1, 8, -8, 3, -3, 1, -1, -5, 5, 9, 1, -9, 1,
+ -1, -1, 1, -1, -4, 4, 1, -1, 3, -3, 1, -10, 10, 1, 2, -1,
+ -1, -2, 6, -6, 2, 11, -11, -2, 3, -3, 1, -4, 4, -1, 3, -3,
+ 1, 3, 12, -3, -5, -12, -1, 5, 2, -2, 1, -1, -7, 1, 13, 7,
+ -1, -13, 2, -2, 4, -4, 1, 2, -2, -1, 1, 14, -14, 1, 1, 1,
+ -1, -5, -1, -1, 5, -1, -6, 2, -15, 15, 6, 1, -1, -8, 8, -2,
+ -4, 4, 1, 1, -1, -1, 16, 2, -16, -2, 2, -2, 4, 3, -4, -3,
+ -1, -4, 4, 1, -17, 17, -1, -9, 1, 1, 9, 1, -5, -1, -1, 5,
+ -7, 7, 6, -6, 3, -3, 18, -18, 19, -19, 1, -10, -1, 10, -5, 5,
+ 20, -20, -3, 1, 3, 1, 8, -1, -8, 2, 7, -1, -21, -2, 5, 21,
+ 5, -1, -7, -5, 1, -6, -5, -11, 6, 22, 11, 1, 1, -22, -3, -1,
+ 3, -1, 3, -3, -23, 4, -4, 1, 23, -1, 1, -1, 1, -2, 2, -1 ]
+ },
+ RVMap { eob_sym: 4, esc_sym: 11, runtab: [
+ 1, 1, 1, 1, 0, 2, 2, 1, 1, 3, 3, 0, 1, 1, 2, 2,
+ 4, 4, 1, 1, 5, 5, 1, 1, 2, 2, 3, 3, 6, 6, 1, 1,
+ 7, 7, 8, 1, 8, 2, 2, 1, 4, 4, 1, 3, 1, 3, 9, 9,
+ 2, 2, 1, 5, 1, 5, 10, 10, 1, 1, 11, 11, 3, 6, 3, 4,
+ 4, 6, 2, 2, 1, 12, 1, 12, 7, 13, 7, 13, 1, 1, 8, 8,
+ 2, 2, 14, 14, 16, 15, 16, 5, 5, 1, 3, 15, 1, 3, 4, 4,
+ 1, 1, 17, 17, 2, 2, 6, 6, 1, 18, 1, 18, 22, 21, 22, 21,
+ 25, 24, 25, 19, 9, 20, 9, 23, 19, 24, 20, 3, 23, 7, 3, 1,
+ 1, 7, 28, 26, 29, 5, 28, 26, 5, 8, 29, 4, 8, 27, 2, 2,
+ 4, 27, 1, 1, 10, 36, 10, 33, 33, 36, 30, 1, 32, 32, 1, 30,
+ 6, 31, 31, 35, 3, 6, 11, 11, 3, 2, 35, 2, 34, 1, 34, 1,
+ 37, 37, 12, 7, 12, 5, 41, 5, 4, 7, 1, 8, 13, 4, 1, 41,
+ 13, 38, 8, 38, 9, 1, 40, 40, 9, 1, 39, 2, 2, 49, 39, 42,
+ 3, 3, 14, 16, 49, 14, 16, 42, 43, 43, 6, 6, 15, 1, 1, 15,
+ 44, 44, 1, 1, 50, 48, 4, 5, 4, 7, 5, 2, 10, 10, 48, 7,
+ 50, 45, 2, 1, 45, 8, 8, 1, 46, 46, 3, 47, 47, 3, 1, 1 ],
+ valtab: [
+ 1, -1, 2, -2, 0, 1, -1, 3, -3, 1, -1, 0, 4, -4, 2, -2,
+ 1, -1, 5, -5, 1, -1, 6, -6, 3, -3, 2, -2, 1, -1, 7, -7,
+ 1, -1, 1, 8, -1, 4, -4, -8, 2, -2, 9, 3, -9, -3, 1, -1,
+ 5, -5, 10, 2, -10, -2, 1, -1, 11, -11, 1, -1, -4, 2, 4, 3,
+ -3, -2, 6, -6, 12, 1, -12, -1, 2, 1, -2, -1, 13, -13, 2, -2,
+ 7, -7, 1, -1, 1, 1, -1, 3, -3, 14, 5, -1, -14, -5, 4, -4,
+ 15, -15, 1, -1, 8, -8, -3, 3, 16, 1, -16, -1, 1, 1, -1, -1,
+ 1, 1, -1, 1, 2, 1, -2, 1, -1, -1, -1, 6, -1, 3, -6, 17,
+ -17, -3, 1, 1, 1, 4, -1, -1, -4, 3, -1, 5, -3, -1, -9, 9,
+ -5, 1, 18, -18, 2, 1, -2, 1, -1, -1, 1, 19, -1, 1, -19, -1,
+ 4, 1, -1, 1, 7, -4, -2, 2, -7, 10, -1, -10, 1, 20, -1, -20,
+ 1, -1, 2, 4, -2, 5, 1, -5, 6, -4, 21, 4, 2, -6, -21, -1,
+ -2, 1, -4, -1, -3, 22, -1, 1, 3, -22, -1, 11, -11, 1, 1, 1,
+ 8, -8, 2, 2, -1, -2, -2, -1, 1, -1, -5, 5, 2, 23, -23, -2,
+ 1, -1, 24, -24, -1, -1, 7, 6, -7, 5, -6, 12, -3, 3, 1, -5,
+ 1, 1, -12, 25, -1, -5, 5, -25, -1, 1, 9, 1, -1, -9, 26, -26 ]
+ }
+];