| 1 | use nihav_core::io::bitreader::*; |
| 2 | use nihav_core::formats; |
| 3 | use nihav_core::frame::*; |
| 4 | use nihav_core::codecs::*; |
| 5 | use super::ivi::*; |
| 6 | use super::ivibr::*; |
| 7 | |
| 8 | fn calc_quant(glob_q: u32, qd: i16) -> usize { |
| 9 | let qq = (glob_q as i16) + (qd as i16); |
| 10 | if qq < 0 { |
| 11 | 0 |
| 12 | } else if qq > 23 { |
| 13 | 23 |
| 14 | } else { |
| 15 | qq as usize |
| 16 | } |
| 17 | } |
| 18 | |
| 19 | struct Indeo5Parser { |
| 20 | mb_cb: IVICodebook, |
| 21 | |
| 22 | width: usize, |
| 23 | height: usize, |
| 24 | tile_w: usize, |
| 25 | tile_h: usize, |
| 26 | luma_bands: usize, |
| 27 | chroma_bands: usize, |
| 28 | |
| 29 | is_hpel: [bool; 5], |
| 30 | mb_size: [usize; 5], |
| 31 | blk_size: [usize; 5], |
| 32 | } |
| 33 | |
| 34 | impl Indeo5Parser { |
| 35 | fn new() -> Self { |
| 36 | Indeo5Parser { |
| 37 | mb_cb: IVI_CB_ZERO, |
| 38 | |
| 39 | width: 0, |
| 40 | height: 0, |
| 41 | tile_w: 0, |
| 42 | tile_h: 0, |
| 43 | luma_bands: 0, |
| 44 | chroma_bands: 0, |
| 45 | |
| 46 | is_hpel: [false; 5], |
| 47 | mb_size: [0; 5], |
| 48 | blk_size: [0; 5], |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | fn skip_extension(br: &mut BitReader) -> DecoderResult<()> { |
| 54 | loop { |
| 55 | let len = br.read(8)?; |
| 56 | if len == 0 { break; } |
| 57 | br.skip(len * 8)?; |
| 58 | } |
| 59 | Ok(()) |
| 60 | } |
| 61 | |
| 62 | impl IndeoXParser for Indeo5Parser { |
| 63 | #[allow(unused_variables)] |
| 64 | #[allow(unused_assignments)] |
| 65 | fn decode_picture_header(&mut self, br: &mut BitReader) -> DecoderResult<PictureHeader> { |
| 66 | let sync = br.read(5)?; |
| 67 | validate!(sync == 0x1F); |
| 68 | let ftype_idx = br.read(3)?; |
| 69 | validate!(ftype_idx < 5); |
| 70 | let ftype = INDEO5_FRAME_TYPE[ftype_idx as usize]; |
| 71 | let fnum = br.read(8)?; |
| 72 | if ftype == IVIFrameType::Intra { |
| 73 | let gop_flags = br.read(8)?; |
| 74 | let hdr_size; |
| 75 | if (gop_flags & 0x01) != 0 { |
| 76 | hdr_size = br.read(16)?; |
| 77 | } else { |
| 78 | hdr_size = 0; |
| 79 | } |
| 80 | if (gop_flags & 0x20) != 0 { |
| 81 | br.skip(32)?; // lock word |
| 82 | } |
| 83 | self.tile_w = 0; |
| 84 | self.tile_h = 0; |
| 85 | if (gop_flags & 0x40) != 0 { |
| 86 | self.tile_w = 64 << br.read(2)?; |
| 87 | self.tile_h = self.tile_w; |
| 88 | } |
| 89 | validate!(self.tile_w < 256); |
| 90 | self.luma_bands = (br.read(2)? * 3 + 1) as usize; |
| 91 | self.chroma_bands = (br.read(1)? * 3 + 1) as usize; |
| 92 | validate!((self.luma_bands == 4) || (self.luma_bands == 1)); |
| 93 | validate!(self.chroma_bands == 1); |
| 94 | let pic_size_idx = br.read(4)? as usize; |
| 95 | let w; |
| 96 | let h; |
| 97 | if pic_size_idx < 15 { |
| 98 | w = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][0]; |
| 99 | h = INDEO5_PICTURE_SIZE_TAB[pic_size_idx][1]; |
| 100 | } else { |
| 101 | h = br.read(13)? as usize; |
| 102 | w = br.read(13)? as usize; |
| 103 | } |
| 104 | validate!((w != 0) && (h != 0)); |
| 105 | self.width = w; |
| 106 | self.height = h; |
| 107 | |
| 108 | validate!((gop_flags & 0x02) == 0); |
| 109 | if self.tile_w == 0 { |
| 110 | self.tile_w = w; |
| 111 | self.tile_h = h; |
| 112 | } |
| 113 | for b in 0..self.luma_bands+self.chroma_bands { |
| 114 | self.is_hpel[b] = br.read_bool()?; |
| 115 | let mb_scale = br.read(1)?; |
| 116 | self.blk_size[b] = 8 >> br.read(1)?; |
| 117 | self.mb_size[b] = self.blk_size[b] << (1 - mb_scale); |
| 118 | let ext_tr = br.read_bool()?; |
| 119 | validate!(!ext_tr); |
| 120 | let end_marker = br.read(2)?; |
| 121 | validate!(end_marker == 0); |
| 122 | } |
| 123 | if (gop_flags & 0x08) != 0 { |
| 124 | let align = br.read(3)?; |
| 125 | validate!(align == 0); |
| 126 | if br.read_bool()? { |
| 127 | br.skip(24)?; // transparency color |
| 128 | } |
| 129 | } |
| 130 | br.align(); |
| 131 | br.skip(23)?; |
| 132 | if br.read_bool()? { // gop extension |
| 133 | loop { |
| 134 | let v = br.read(16)?; |
| 135 | if (v & 0x8000) == 0 { break; } |
| 136 | } |
| 137 | } |
| 138 | br.align(); |
| 139 | } |
| 140 | if ftype.is_null() { |
| 141 | br.align(); |
| 142 | return Ok(PictureHeader::new_null(ftype)); |
| 143 | } |
| 144 | let flags = br.read(8)?; |
| 145 | let size; |
| 146 | if (flags & 0x01) != 0 { |
| 147 | size = br.read(24)?; |
| 148 | } else { |
| 149 | size = 0; |
| 150 | } |
| 151 | let checksum; |
| 152 | if (flags & 0x10) != 0 { |
| 153 | checksum = br.read(16)?; |
| 154 | } else { |
| 155 | checksum = 0; |
| 156 | } |
| 157 | if (flags & 0x20) != 0 { |
| 158 | skip_extension(br)?; |
| 159 | } |
| 160 | let in_q = (flags & 0x08) != 0; |
| 161 | self.mb_cb = br.read_ivi_codebook_desc(true, (flags & 0x40) != 0)?; |
| 162 | br.skip(3)?; |
| 163 | br.align(); |
| 164 | |
| 165 | Ok(PictureHeader::new(ftype, self.width, self.height, self.tile_w, self.tile_h, false, self.luma_bands, self.chroma_bands, in_q)) |
| 166 | } |
| 167 | |
| 168 | #[allow(unused_variables)] |
| 169 | fn decode_band_header(&mut self, br: &mut BitReader, pic_hdr: &PictureHeader, plane_no: usize, band_no: usize) -> DecoderResult<BandHeader> { |
| 170 | let band_flags = br.read(8)?; |
| 171 | |
| 172 | if (band_flags & 0x01) != 0 { |
| 173 | br.align(); |
| 174 | return Ok(BandHeader::new_empty(plane_no, band_no)); |
| 175 | } |
| 176 | let inherit_mv = (band_flags & 0x02) != 0; |
| 177 | let has_qdelta = (band_flags & 0x04) != 0; |
| 178 | let inherit_qd = ((band_flags & 0x08) != 0) || !has_qdelta; |
| 179 | let data_size: usize; |
| 180 | if (band_flags & 0x80) != 0 { |
| 181 | data_size = br.read(24)? as usize; |
| 182 | } else { |
| 183 | data_size = 0; |
| 184 | } |
| 185 | validate!(data_size <= ((br.left() / 8) as usize)); |
| 186 | |
| 187 | let num_corr: usize; |
| 188 | let mut corr_map: [u8; CORR_MAP_SIZE] = [0; CORR_MAP_SIZE]; |
| 189 | if (band_flags & 0x10) != 0 { |
| 190 | num_corr = br.read(8)? as usize; |
| 191 | validate!(num_corr*2 <= CORR_MAP_SIZE); |
| 192 | for i in 0..num_corr*2 { |
| 193 | corr_map[i] = br.read(8)? as u8; |
| 194 | } |
| 195 | } else { |
| 196 | num_corr = 0; |
| 197 | } |
| 198 | let rvmap_idx; |
| 199 | if (band_flags & 0x40) != 0 { |
| 200 | rvmap_idx = br.read(3)? as usize; |
| 201 | } else { |
| 202 | rvmap_idx = 8; |
| 203 | } |
| 204 | let blk_cb = br.read_ivi_codebook_desc(false, (band_flags & 0x80) != 0)?; |
| 205 | if br.read_bool()? { |
| 206 | br.skip(16)?; // checksum |
| 207 | } |
| 208 | let band_q = br.read(5)?; |
| 209 | if (band_flags & 0x20) != 0 { |
| 210 | skip_extension(br)?; |
| 211 | } |
| 212 | br.align(); |
| 213 | |
| 214 | let tr; |
| 215 | let txtype; |
| 216 | let band_id = if plane_no == 0 { band_no } else { self.luma_bands }; |
| 217 | match plane_no { |
| 218 | 0 => { |
| 219 | let scan = INDEO5_SCAN8X8[band_no]; |
| 220 | let qintra; |
| 221 | let qinter; |
| 222 | validate!(self.blk_size[band_id] == 8); |
| 223 | match band_no { |
| 224 | 0 => { |
| 225 | tr = IVITransformType::Slant(TSize::T8x8, TDir::TwoD); |
| 226 | if self.luma_bands == 1 { |
| 227 | qintra = INDEO5_Q8_INTRA[0]; |
| 228 | qinter = INDEO5_Q8_INTER[0]; |
| 229 | } else { |
| 230 | qintra = INDEO5_Q8_INTRA[1]; |
| 231 | qinter = INDEO5_Q8_INTER[1]; |
| 232 | } |
| 233 | }, |
| 234 | 1 => { |
| 235 | tr = IVITransformType::Slant(TSize::T8x8, TDir::Row); |
| 236 | qintra = INDEO5_Q8_INTRA[2]; |
| 237 | qinter = INDEO5_Q8_INTER[2]; |
| 238 | }, |
| 239 | 2 => { |
| 240 | tr = IVITransformType::Slant(TSize::T8x8, TDir::Col); |
| 241 | qintra = INDEO5_Q8_INTRA[3]; |
| 242 | qinter = INDEO5_Q8_INTER[3]; |
| 243 | }, |
| 244 | 3 => { |
| 245 | tr = IVITransformType::None(TSize::T8x8); |
| 246 | qintra = INDEO5_Q8_INTRA[4]; |
| 247 | qinter = INDEO5_Q8_INTER[4]; |
| 248 | }, |
| 249 | _ => { unreachable!(); } |
| 250 | }; |
| 251 | txtype = TxType::Transform8(TxParams8x8::new(qintra, qinter, scan)); |
| 252 | }, |
| 253 | 1 | 2 => { |
| 254 | validate!(self.blk_size[band_id] == 4); |
| 255 | tr = IVITransformType::Slant(TSize::T4x4, TDir::TwoD); |
| 256 | let scan = INDEO5_SCAN4X4; |
| 257 | let qintra = INDEO5_Q4_INTRA; |
| 258 | let qinter = INDEO5_Q4_INTER; |
| 259 | txtype = TxType::Transform4(TxParams4x4::new(qintra, qinter, scan)); |
| 260 | }, |
| 261 | _ => { unreachable!(); } |
| 262 | }; |
| 263 | |
| 264 | 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)) |
| 265 | } |
| 266 | |
| 267 | 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<()> { |
| 268 | let mut mv_x = 0; |
| 269 | let mut mv_y = 0; |
| 270 | let band_id = if pic_hdr.luma_bands == 4 { band.band_no + 1 } else { 0 }; |
| 271 | let mut mb_idx = 0; |
| 272 | for mb_y in 0..tile.mb_h { |
| 273 | for mb_x in 0..tile.mb_w { |
| 274 | let mut mb = MB::new(tile.pos_x + mb_x * band.mb_size, tile.pos_y + mb_y * band.mb_size); |
| 275 | if !br.read_bool()? { |
| 276 | if pic_hdr.ftype.is_intra() { |
| 277 | mb.mtype = MBType::Intra; |
| 278 | } else if band.inherit_mv { |
| 279 | if let Some(ref tileref) = ref_tile { |
| 280 | mb.mtype = tileref.mb[mb_idx].mtype; |
| 281 | } else { |
| 282 | return Err(DecoderError::MissingReference); |
| 283 | } |
| 284 | } else { |
| 285 | mb.mtype = if br.read_bool()? { MBType::Inter } else { MBType::Intra }; |
| 286 | } |
| 287 | if band.mb_size == band.blk_size { |
| 288 | mb.cbp = br.read(1)? as u8; |
| 289 | } else { |
| 290 | mb.cbp = br.read(4)? as u8; |
| 291 | } |
| 292 | let q; |
| 293 | if band.has_qdelta { |
| 294 | if band.inherit_qd { |
| 295 | if let Some(ref tileref) = ref_tile { |
| 296 | mb.qd = tileref.mb[mb_idx].qd; |
| 297 | q = calc_quant(band.quant, mb.qd); |
| 298 | } else { |
| 299 | return Err(DecoderError::MissingReference); |
| 300 | } |
| 301 | } else if (mb.cbp != 0) || ((band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q) { |
| 302 | mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16; |
| 303 | q = calc_quant(band.quant, mb.qd); |
| 304 | } else { |
| 305 | q = band.quant as usize; |
| 306 | } |
| 307 | } else { |
| 308 | q = band.quant as usize; |
| 309 | } |
| 310 | |
| 311 | if mb.mtype == MBType::Intra { |
| 312 | if band.blk_size == 8 { |
| 313 | mb.q = INDEO5_QSCALE8_INTRA[band_id][q]; |
| 314 | } else { |
| 315 | mb.q = INDEO5_QSCALE4_INTRA[q]; |
| 316 | } |
| 317 | } else { |
| 318 | if band.blk_size == 8 { |
| 319 | mb.q = INDEO5_QSCALE8_INTER[band_id][q]; |
| 320 | } else { |
| 321 | mb.q = INDEO5_QSCALE4_INTER[q]; |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | if mb.mtype != MBType::Intra { |
| 326 | if band.inherit_mv { |
| 327 | if let Some(ref tileref) = ref_tile { |
| 328 | let mx = tileref.mb[mb_idx].mv_x; |
| 329 | let my = tileref.mb[mb_idx].mv_y; |
| 330 | if mv_scale == 0 { |
| 331 | mb.mv_x = mx; |
| 332 | mb.mv_y = my; |
| 333 | } else { |
| 334 | mb.mv_x = scale_mv(mx, mv_scale); |
| 335 | mb.mv_y = scale_mv(my, mv_scale); |
| 336 | } |
| 337 | } |
| 338 | } else { |
| 339 | mv_y += br.read_ivi_cb_s(&self.mb_cb)?; |
| 340 | mv_x += br.read_ivi_cb_s(&self.mb_cb)?; |
| 341 | mb.mv_x = mv_x; |
| 342 | mb.mv_y = mv_y; |
| 343 | } |
| 344 | } |
| 345 | } else { |
| 346 | validate!(!pic_hdr.ftype.is_intra()); |
| 347 | mb.mtype = MBType::Inter; |
| 348 | mb.cbp = 0; |
| 349 | mb.qd = 0; |
| 350 | if (band.plane_no == 0) && (band.band_no == 0) && pic_hdr.in_q { |
| 351 | mb.qd = br.read_ivi_cb_s(&self.mb_cb)? as i16; |
| 352 | let q = calc_quant(band.quant, mb.qd); |
| 353 | if mb.mtype == MBType::Intra { |
| 354 | if band.blk_size == 8 { |
| 355 | mb.q = INDEO5_QSCALE8_INTRA[band_id][q]; |
| 356 | } else { |
| 357 | mb.q = INDEO5_QSCALE4_INTRA[q]; |
| 358 | } |
| 359 | } else { |
| 360 | if band.blk_size == 8 { |
| 361 | mb.q = INDEO5_QSCALE8_INTER[band_id][q]; |
| 362 | } else { |
| 363 | mb.q = INDEO5_QSCALE4_INTER[q]; |
| 364 | } |
| 365 | } |
| 366 | } |
| 367 | if band.inherit_mv { |
| 368 | if let Some(ref tileref) = ref_tile { |
| 369 | let mx = tileref.mb[mb_idx].mv_x; |
| 370 | let my = tileref.mb[mb_idx].mv_y; |
| 371 | if mv_scale == 0 { |
| 372 | mb.mv_x = mx; |
| 373 | mb.mv_y = my; |
| 374 | } else { |
| 375 | mb.mv_x = scale_mv(mx, mv_scale); |
| 376 | mb.mv_y = scale_mv(my, mv_scale); |
| 377 | } |
| 378 | } |
| 379 | } |
| 380 | } |
| 381 | tile.mb[mb_idx] = mb; |
| 382 | mb_idx += 1; |
| 383 | } |
| 384 | } |
| 385 | br.align(); |
| 386 | Ok(()) |
| 387 | } |
| 388 | |
| 389 | fn recombine_plane(&mut self, src: &[i16], sstride: usize, dst: &mut [u8], dstride: usize, w: usize, h: usize) { |
| 390 | let mut idx0 = 0; |
| 391 | let mut idx1 = w / 2; |
| 392 | let mut idx2 = (h / 2) * sstride; |
| 393 | let mut idx3 = idx2 + idx1; |
| 394 | let mut bidx1 = idx1; |
| 395 | let mut bidx3 = idx3; |
| 396 | let mut oidx0 = 0; |
| 397 | let mut oidx1 = dstride; |
| 398 | let filt_lo = |a: i16, b: i16| a + b; |
| 399 | let filt_hi = |a: i16, b: i16, c: i16| a - b * 6 + c; |
| 400 | |
| 401 | for _ in 0..(h/2) { |
| 402 | let mut b0_1 = src[idx0]; |
| 403 | let mut b0_2 = src[idx0 + sstride]; |
| 404 | let mut b1_1 = src[bidx1]; |
| 405 | let mut b1_2 = src[idx1]; |
| 406 | let mut b1_3 = filt_hi(b1_1, b1_2, src[idx1 + sstride]); |
| 407 | let mut b2_1; |
| 408 | let mut b2_2 = src[idx2]; |
| 409 | let mut b2_3 = b2_2; |
| 410 | let mut b2_4; |
| 411 | let mut b2_5 = src[idx2 + sstride]; |
| 412 | let mut b2_6 = b2_5; |
| 413 | let mut b3_1; |
| 414 | let mut b3_2 = src[bidx3]; |
| 415 | let mut b3_3 = b3_2; |
| 416 | let mut b3_4; |
| 417 | let mut b3_5 = src[idx3]; |
| 418 | let mut b3_6 = b3_5; |
| 419 | let mut b3_8 = filt_hi(b3_2, b3_5, src[idx3 + sstride]); |
| 420 | let mut b3_9 = b3_8; |
| 421 | let mut b3_7; |
| 422 | |
| 423 | for x in 0..(w/2) { |
| 424 | b2_1 = b2_2; |
| 425 | b2_2 = b2_3; |
| 426 | b2_4 = b2_5; |
| 427 | b2_5 = b2_6; |
| 428 | b3_1 = b3_2; |
| 429 | b3_2 = b3_3; |
| 430 | b3_4 = b3_5; |
| 431 | b3_5 = b3_6; |
| 432 | b3_7 = b3_8; |
| 433 | b3_8 = b3_9; |
| 434 | |
| 435 | let tmp0 = b0_1; |
| 436 | let tmp1 = b0_2; |
| 437 | b0_1 = src[idx0 + x + 1]; |
| 438 | b0_2 = src[idx0 + x + 1 + sstride]; |
| 439 | let mut p0 = tmp0 << 4; |
| 440 | let mut p1 = (tmp0 + b0_1) << 3; |
| 441 | let mut p2 = (tmp0 + tmp1) << 3; |
| 442 | let mut p3 = (tmp0 + tmp1 + b0_1 + b0_2) << 2; |
| 443 | |
| 444 | let tmp0 = b1_1; |
| 445 | let tmp1 = b1_2; |
| 446 | let tmp2 = filt_lo(tmp0, tmp1); |
| 447 | let tmp3 = filt_hi(tmp0, tmp1, b1_3); |
| 448 | b1_2 = src[ idx1 + x + 1]; |
| 449 | b1_1 = src[bidx1 + x + 1]; |
| 450 | b1_3 = filt_hi(b1_1, b1_2, src[idx1 + x + 1 + sstride]); |
| 451 | p0 += tmp2 << 3; |
| 452 | p1 += (tmp2 + b1_1 + b1_2) << 2; |
| 453 | p2 += tmp3 << 2; |
| 454 | p3 += (tmp3 + b1_3) << 1; |
| 455 | |
| 456 | b2_3 = src[idx2 + x + 1]; |
| 457 | b2_6 = src[idx2 + x + 1 + sstride]; |
| 458 | let tmp0 = filt_lo(b2_1, b2_2); |
| 459 | let tmp1 = filt_hi(b2_1, b2_2, b2_3); |
| 460 | p0 += tmp0 << 3; |
| 461 | p1 += tmp1 << 2; |
| 462 | p2 += (tmp0 + filt_lo(b2_4, b2_5)) << 2; |
| 463 | p3 += (tmp1 + filt_hi(b2_4, b2_5, b2_6)) << 1; |
| 464 | |
| 465 | b3_6 = src[idx3 + x + 1]; |
| 466 | b3_3 = src[bidx3 + x + 1]; |
| 467 | b3_9 = filt_hi(b3_3, b3_6, src[idx3 + x + 1 + sstride]); |
| 468 | let tmp0 = b3_1 + b3_4; |
| 469 | let tmp1 = b3_2 + b3_5; |
| 470 | let tmp2 = b3_3 + b3_6; |
| 471 | p0 += filt_lo(tmp0, tmp1) << 2; |
| 472 | p1 += filt_hi(tmp0, tmp1, tmp2) << 1; |
| 473 | p2 += filt_lo(b3_7, b3_8) << 1; |
| 474 | p3 += filt_hi(b3_7, b3_8, b3_9) << 0; |
| 475 | |
| 476 | dst[oidx0 + x * 2 + 0] = clip8((p0 >> 6) + 128); |
| 477 | dst[oidx0 + x * 2 + 1] = clip8((p1 >> 6) + 128); |
| 478 | dst[oidx1 + x * 2 + 0] = clip8((p2 >> 6) + 128); |
| 479 | dst[oidx1 + x * 2 + 1] = clip8((p3 >> 6) + 128); |
| 480 | } |
| 481 | bidx1 = idx1; |
| 482 | bidx3 = idx3; |
| 483 | idx0 += sstride; |
| 484 | idx1 += sstride; |
| 485 | idx2 += sstride; |
| 486 | idx3 += sstride; |
| 487 | oidx0 += dstride * 2; |
| 488 | oidx1 += dstride * 2; |
| 489 | } |
| 490 | } |
| 491 | } |
| 492 | |
| 493 | struct Indeo5Decoder { |
| 494 | info: NACodecInfoRef, |
| 495 | dec: IVIDecoder, |
| 496 | ip: Indeo5Parser, |
| 497 | } |
| 498 | |
| 499 | impl Indeo5Decoder { |
| 500 | fn new() -> Self { |
| 501 | Indeo5Decoder { |
| 502 | info: NACodecInfo::new_dummy(), |
| 503 | dec: IVIDecoder::new(), |
| 504 | ip: Indeo5Parser::new(), |
| 505 | } |
| 506 | } |
| 507 | } |
| 508 | |
| 509 | impl NADecoder for Indeo5Decoder { |
| 510 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
| 511 | if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { |
| 512 | let w = vinfo.get_width(); |
| 513 | let h = vinfo.get_height(); |
| 514 | let f = vinfo.is_flipped(); |
| 515 | let fmt = formats::YUV410_FORMAT; |
| 516 | let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt)); |
| 517 | self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); |
| 518 | Ok(()) |
| 519 | } else { |
| 520 | Err(DecoderError::InvalidData) |
| 521 | } |
| 522 | } |
| 523 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
| 524 | let src = pkt.get_buffer(); |
| 525 | let mut br = BitReader::new(src.as_slice(), src.len(), BitReaderMode::LE); |
| 526 | |
| 527 | let bufinfo = self.dec.decode_frame(&mut self.ip, &mut br)?; |
| 528 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); |
| 529 | frm.set_keyframe(self.dec.is_intra()); |
| 530 | frm.set_frame_type(self.dec.get_frame_type()); |
| 531 | Ok(frm.into_ref()) |
| 532 | } |
| 533 | fn flush(&mut self) { |
| 534 | self.dec.flush(); |
| 535 | } |
| 536 | } |
| 537 | |
| 538 | const INDEO5_PICTURE_SIZE_TAB: [[usize; 2]; 15] = [ |
| 539 | [640, 480], [320, 240], [160, 120], [704, 480], [352, 240], [352, 288], [176, 144], |
| 540 | [240, 180], [640, 240], [704, 240], [80, 60], [88, 72], [0, 0], [0, 0], [0, 0] |
| 541 | ]; |
| 542 | |
| 543 | const INDEO5_FRAME_TYPE: [IVIFrameType; 5] = [ |
| 544 | IVIFrameType::Intra, IVIFrameType::Inter, IVIFrameType::InterScal, |
| 545 | IVIFrameType::InterDroppable, IVIFrameType::NULL, |
| 546 | ]; |
| 547 | |
| 548 | const INDEO5_QUANT8X8_INTRA: [[u16; 64]; 5] = [ |
| 549 | [ |
| 550 | 0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a, |
| 551 | 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a, |
| 552 | 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72, |
| 553 | 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a, |
| 554 | 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e, |
| 555 | 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6, |
| 556 | 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca, |
| 557 | 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe, |
| 558 | ], [ |
| 559 | 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a, |
| 560 | 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e, |
| 561 | 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62, |
| 562 | 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66, |
| 563 | 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a, |
| 564 | 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e, |
| 565 | 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72, |
| 566 | 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76, |
| 567 | ], [ |
| 568 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 569 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 570 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 571 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 572 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 573 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 574 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 575 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 576 | ], [ |
| 577 | 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, |
| 578 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, |
| 579 | 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, |
| 580 | 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, |
| 581 | 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, |
| 582 | 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, |
| 583 | 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, |
| 584 | 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, |
| 585 | ], [ |
| 586 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 587 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 588 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 589 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 590 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 591 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 592 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 593 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 594 | ] |
| 595 | ]; |
| 596 | const INDEO5_QUANT8X8_INTER: [[u16; 64]; 5] = [ |
| 597 | [ |
| 598 | 0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a, |
| 599 | 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e, |
| 600 | 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62, |
| 601 | 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66, |
| 602 | 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a, |
| 603 | 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e, |
| 604 | 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72, |
| 605 | 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76, |
| 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 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 617 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 618 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 619 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 620 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 621 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 622 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 623 | 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, |
| 624 | ], [ |
| 625 | 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, |
| 626 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, |
| 627 | 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, |
| 628 | 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, |
| 629 | 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, |
| 630 | 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, |
| 631 | 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, |
| 632 | 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, |
| 633 | ], [ |
| 634 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 635 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 636 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 637 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 638 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 639 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 640 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 641 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, |
| 642 | ] |
| 643 | ]; |
| 644 | const INDEO5_QUANT4X4_INTRA: [u16; 16] = [ |
| 645 | 0x1e, 0x3e, 0x4a, 0x52, |
| 646 | 0x3e, 0x4a, 0x52, 0x5e, |
| 647 | 0x4a, 0x52, 0x5e, 0x7a, |
| 648 | 0x52, 0x5e, 0x7a, 0x92 |
| 649 | ]; |
| 650 | const INDEO5_QUANT4X4_INTER: [u16; 16] = [ |
| 651 | 0x1e, 0x3e, 0x4a, 0x52, |
| 652 | 0x3e, 0x4a, 0x52, 0x56, |
| 653 | 0x4a, 0x52, 0x56, 0x5e, |
| 654 | 0x52, 0x56, 0x5e, 0x66 |
| 655 | ]; |
| 656 | const INDEO5_Q8_INTRA: [&[u16; 64]; 5] = [ |
| 657 | &INDEO5_QUANT8X8_INTRA[0], &INDEO5_QUANT8X8_INTRA[1], &INDEO5_QUANT8X8_INTRA[2], |
| 658 | &INDEO5_QUANT8X8_INTRA[3], &INDEO5_QUANT8X8_INTRA[4], |
| 659 | ]; |
| 660 | const INDEO5_Q8_INTER: [&[u16; 64]; 5] = [ |
| 661 | &INDEO5_QUANT8X8_INTER[0], &INDEO5_QUANT8X8_INTER[1], &INDEO5_QUANT8X8_INTER[2], |
| 662 | &INDEO5_QUANT8X8_INTER[3], &INDEO5_QUANT8X8_INTER[4], |
| 663 | ]; |
| 664 | const INDEO5_Q4_INTRA: &[u16; 16] = &INDEO5_QUANT4X4_INTRA; |
| 665 | const INDEO5_Q4_INTER: &[u16; 16] = &INDEO5_QUANT4X4_INTER; |
| 666 | |
| 667 | const INDEO5_SCAN8X8: [&[usize; 64]; 4] = [ |
| 668 | &ZIGZAG, &IVI_SCAN_8X8_VER, &IVI_SCAN_8X8_HOR, &IVI_SCAN_8X8_HOR |
| 669 | ]; |
| 670 | const INDEO5_SCAN4X4: &[usize; 16] = &IVI_SCAN_4X4; |
| 671 | |
| 672 | const INDEO5_QSCALE8_INTRA: [[u8; 24]; 5] = [ |
| 673 | [ |
| 674 | 0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20, |
| 675 | 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c, |
| 676 | ], [ |
| 677 | 0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c, |
| 678 | 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c, |
| 679 | ], [ |
| 680 | 0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e, |
| 681 | 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95, |
| 682 | ], [ |
| 683 | 0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d, |
| 684 | 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b, |
| 685 | ], [ |
| 686 | 0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b, |
| 687 | 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4, |
| 688 | ] |
| 689 | ]; |
| 690 | const INDEO5_QSCALE8_INTER: [[u8; 24]; 5] = [ |
| 691 | [ |
| 692 | 0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22, |
| 693 | 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a, |
| 694 | ], [ |
| 695 | 0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35, |
| 696 | 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e, |
| 697 | ], [ |
| 698 | 0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51, |
| 699 | 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97, |
| 700 | ], [ |
| 701 | 0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39, |
| 702 | 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62, |
| 703 | ], [ |
| 704 | 0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80, |
| 705 | 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba |
| 706 | ] |
| 707 | ]; |
| 708 | const INDEO5_QSCALE4_INTRA: [u8; 24] = [ |
| 709 | 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14, |
| 710 | 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 |
| 711 | ]; |
| 712 | const INDEO5_QSCALE4_INTER: [u8; 24] = [ |
| 713 | 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 714 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 |
| 715 | ]; |
| 716 | |
| 717 | pub fn get_decoder() -> Box<dyn NADecoder> { |
| 718 | Box::new(Indeo5Decoder::new()) |
| 719 | } |
| 720 | |
| 721 | #[cfg(test)] |
| 722 | mod test { |
| 723 | use nihav_core::codecs::RegisteredDecoders; |
| 724 | use nihav_core::demuxers::RegisteredDemuxers; |
| 725 | use nihav_core::test::dec_video::*; |
| 726 | use crate::codecs::indeo_register_all_codecs; |
| 727 | use nihav_commonfmt::demuxers::generic_register_all_demuxers; |
| 728 | #[test] |
| 729 | fn test_indeo5() { |
| 730 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 731 | generic_register_all_demuxers(&mut dmx_reg); |
| 732 | let mut dec_reg = RegisteredDecoders::new(); |
| 733 | indeo_register_all_codecs(&mut dec_reg); |
| 734 | |
| 735 | test_file_decoding("avi", "assets/Indeo/IV5/sample.avi", /*None*/Some(2), true, false, None, &dmx_reg, &dec_reg); |
| 736 | // test_file_decoding("avi", "assets/Indeo/IV5/W32mdl_1.avi", None/*Some(2)*/, true, false, Some("iv5")); |
| 737 | //panic!("the end"); |
| 738 | } |
| 739 | } |