1 use nihav_core::io::bitreader::*;
2 use nihav_core::io::codebook::*;
3 use nihav_core::formats;
4 use nihav_core::frame::*;
5 use nihav_core::codecs::*;
6 use nihav_codec_support::codecs::{MV, ZIGZAG};
7 use nihav_codec_support::codecs::blockdsp;
8 use nihav_codec_support::codecs::h263::*;
9 use nihav_codec_support::codecs::h263::code::{H263_INTERP_FUNCS, H263_INTERP_AVG_FUNCS};
10 use nihav_codec_support::codecs::h263::decoder::*;
11 use nihav_codec_support::codecs::h263::data::*;
15 intra_mcbpc_cb: Codebook<u8>,
16 inter_mcbpc_cb: Codebook<u8>,
17 cbpy_cb: Codebook<u8>,
18 rl_cb: Codebook<H263RLSym>,
19 aic_rl_cb: Codebook<H263RLSym>,
24 struct I263BlockDSP {}
26 struct Intel263Decoder {
31 lastframe: Option<NABufferType>,
35 struct Intel263BR<'a> {
52 const ROW_SHIFT: u8 = 8;
53 const COL_SHIFT: u8 = 14;
55 #[allow(clippy::erasing_op)]
56 fn idct_row(row: &mut [i16]) {
57 let in0 = ((i32::from(row[0])) << 11) + (1 << (ROW_SHIFT - 1));
58 let in1 = (i32::from(row[4])) << 11;
59 let in2 = i32::from(row[6]);
60 let in3 = i32::from(row[2]);
61 let in4 = i32::from(row[1]);
62 let in5 = i32::from(row[7]);
63 let in6 = i32::from(row[5]);
64 let in7 = i32::from(row[3]);
66 let tmp = W7 * (in4 + in5);
67 let a4 = tmp + (W1 - W7) * in4;
68 let a5 = tmp - (W1 + W7) * in5;
70 let tmp = W3 * (in6 + in7);
71 let a6 = tmp - (W3 - W5) * in6;
72 let a7 = tmp - (W3 + W5) * in7;
77 let t1 = W6 * (in2 + in3);
78 let a2 = t1 - (W2 + W6) * in2;
79 let a3 = t1 + (W2 - W6) * in3;
89 let b2 = (W8 * (b4 + t2) + 128) >> 8;
90 let b4 = (W8 * (b4 - t2) + 128) >> 8;
92 row[0] = ((b7 + b1) >> ROW_SHIFT) as i16;
93 row[7] = ((b7 - b1) >> ROW_SHIFT) as i16;
94 row[1] = ((b3 + b2) >> ROW_SHIFT) as i16;
95 row[6] = ((b3 - b2) >> ROW_SHIFT) as i16;
96 row[2] = ((b0 + b4) >> ROW_SHIFT) as i16;
97 row[5] = ((b0 - b4) >> ROW_SHIFT) as i16;
98 row[3] = ((b5 + b6) >> ROW_SHIFT) as i16;
99 row[4] = ((b5 - b6) >> ROW_SHIFT) as i16;
102 #[allow(clippy::erasing_op)]
103 fn idct_col(blk: &mut [i16; 64], off: usize) {
104 let in0 = ((i32::from(blk[off + 0*8])) << 8) + (1 << (COL_SHIFT - 1));
105 let in1 = (i32::from(blk[off + 4*8])) << 8;
106 let in2 = i32::from(blk[off + 6*8]);
107 let in3 = i32::from(blk[off + 2*8]);
108 let in4 = i32::from(blk[off + 1*8]);
109 let in5 = i32::from(blk[off + 7*8]);
110 let in6 = i32::from(blk[off + 5*8]);
111 let in7 = i32::from(blk[off + 3*8]);
113 let tmp = W7 * (in4 + in5);
114 let a4 = (tmp + (W1 - W7) * in4) >> 3;
115 let a5 = (tmp - (W1 + W7) * in5) >> 3;
117 let tmp = W3 * (in6 + in7);
118 let a6 = (tmp - (W3 - W5) * in6) >> 3;
119 let a7 = (tmp - (W3 + W5) * in7) >> 3;
124 let t1 = W6 * (in2 + in3);
125 let a2 = (t1 - (W2 + W6) * in2) >> 3;
126 let a3 = (t1 + (W2 - W6) * in3) >> 3;
136 let b2 = (W8 * (b4 + t2) + 128) >> 8;
137 let b4 = (W8 * (b4 - t2) + 128) >> 8;
139 blk[off + 0*8] = ((b7 + b1) >> COL_SHIFT) as i16;
140 blk[off + 7*8] = ((b7 - b1) >> COL_SHIFT) as i16;
141 blk[off + 1*8] = ((b3 + b2) >> COL_SHIFT) as i16;
142 blk[off + 6*8] = ((b3 - b2) >> COL_SHIFT) as i16;
143 blk[off + 2*8] = ((b0 + b4) >> COL_SHIFT) as i16;
144 blk[off + 5*8] = ((b0 - b4) >> COL_SHIFT) as i16;
145 blk[off + 3*8] = ((b5 + b6) >> COL_SHIFT) as i16;
146 blk[off + 4*8] = ((b5 - b6) >> COL_SHIFT) as i16;
149 const FILTER_STRENGTH: [u8; 32] = [
150 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7,
151 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12
154 #[allow(clippy::erasing_op)]
155 fn deblock_hor(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
156 let stride = buf.get_stride(comp);
157 let dptr = buf.get_data_mut().unwrap();
158 let buf = dptr.as_mut_slice();
160 let a = i16::from(buf[off - 2 * stride + x]);
161 let b = i16::from(buf[off - 1 * stride + x]);
162 let c = i16::from(buf[off + 0 * stride + x]);
163 let d = i16::from(buf[off + 1 * stride + x]);
164 let diff = (3 * (a - d) + 8 * (c - b)) / 16;
165 if (diff != 0) && (diff > -24) && (diff < 24) {
166 let d1a = (diff.abs() - 2 * (diff.abs() - i16::from(strength)).max(0)).max(0);
167 let d1 = if diff < 0 { -d1a } else { d1a };
169 buf[off - 1 * stride + x] = (b + d1).max(0).min(255) as u8;
170 buf[off + 0 * stride + x] = (c - d1).max(0).min(255) as u8;
175 fn deblock_ver(buf: &mut NAVideoBuffer<u8>, comp: usize, strength: u8, off: usize) {
176 let stride = buf.get_stride(comp);
177 let dptr = buf.get_data_mut().unwrap();
178 let buf = dptr.as_mut_slice();
180 let a = i16::from(buf[off - 2 + y * stride]);
181 let b = i16::from(buf[off - 1 + y * stride]);
182 let c = i16::from(buf[off + 0 + y * stride]);
183 let d = i16::from(buf[off + 1 + y * stride]);
184 let diff = (3 * (a - d) + 8 * (c - b)) / 16;
185 if (diff != 0) && (diff > -24) && (diff < 24) {
186 let d1a = (diff.abs() - 2 * (diff.abs() - i16::from(strength)).max(0)).max(0);
187 let d1 = if diff < 0 { -d1a } else { d1a };
189 buf[off - 1 + y * stride] = (b + d1).max(0).min(255) as u8;
190 buf[off + y * stride] = (c - d1).max(0).min(255) as u8;
195 impl BlockDSP for I263BlockDSP {
196 fn idct(&self, blk: &mut [i16; 64]) {
197 for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
198 for i in 0..8 { idct_col(blk, i); }
200 fn copy_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
201 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
202 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
204 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
206 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_FUNCS);
207 blockdsp::copy_block(&mut dst, src.clone(), 1, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
208 blockdsp::copy_block(&mut dst, src, 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
210 fn copy_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
211 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
214 let xadd = (i & 1) * 8;
215 let yadd = (i & 2) * 4;
216 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
218 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mvs[i].x >> 1, mvs[i].y >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
221 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
222 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
223 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
224 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
226 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
229 fn avg_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
230 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
231 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
233 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
235 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_AVG_FUNCS);
236 blockdsp::copy_block(&mut dst, src.clone(), 1, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
237 blockdsp::copy_block(&mut dst, src, 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
239 fn avg_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
240 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
243 let xadd = (i & 1) * 8;
244 let yadd = (i & 2) * 4;
245 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
247 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos + xadd, ypos + yadd, mvs[i].x >> 1, mvs[i].y >> 1, 8, 8, 0, 1, mode, H263_INTERP_AVG_FUNCS);
250 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
251 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
252 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
253 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
255 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_AVG_FUNCS);
258 fn filter_row(&self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
259 let stride = buf.get_stride(0);
260 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
261 for mb_x in 0..mb_w {
263 let coded0 = cbpi.is_coded(mb_x, 0);
264 let coded1 = cbpi.is_coded(mb_x, 1);
265 let q = cbpi.get_q(mb_w + mb_x);
266 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
268 if coded0 && cbpi.is_coded_top(mb_x, 0) { deblock_hor(buf, 0, str, coff); }
269 if coded1 && cbpi.is_coded_top(mb_x, 1) { deblock_hor(buf, 0, str, coff + 8); }
271 let coff = off + 8 * stride;
272 if cbpi.is_coded(mb_x, 2) && coded0 { deblock_hor(buf, 0, q, coff); }
273 if cbpi.is_coded(mb_x, 3) && coded1 { deblock_hor(buf, 0, q, coff + 8); }
276 let mut leftt = false;
277 let mut leftc = false;
278 let mut off = buf.get_offset(0) + mb_y * 16 * stride;
279 for mb_x in 0..mb_w {
280 let ctop0 = cbpi.is_coded_top(mb_x, 0);
281 let ctop1 = cbpi.is_coded_top(mb_x, 0);
282 let ccur0 = cbpi.is_coded(mb_x, 0);
283 let ccur1 = cbpi.is_coded(mb_x, 1);
284 let q = cbpi.get_q(mb_w + mb_x);
285 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
287 let coff = off - 8 * stride;
288 let qtop = cbpi.get_q(mb_x);
289 let strtop = if qtop < 32 { FILTER_STRENGTH[qtop as usize] } else { 0 };
290 if leftt && ctop0 { deblock_ver(buf, 0, strtop, coff); }
291 if ctop0 && ctop1 { deblock_ver(buf, 0, strtop, coff + 8); }
293 if leftc && ccur0 { deblock_ver(buf, 0, str, off); }
294 if ccur0 && ccur1 { deblock_ver(buf, 0, str, off + 8); }
299 let strideu = buf.get_stride(1);
300 let stridev = buf.get_stride(2);
301 let offu = buf.get_offset(1) + mb_y * 8 * strideu;
302 let offv = buf.get_offset(2) + mb_y * 8 * stridev;
304 for mb_x in 0..mb_w {
305 let ctu = cbpi.is_coded_top(mb_x, 4);
306 let ccu = cbpi.is_coded(mb_x, 4);
307 let ctv = cbpi.is_coded_top(mb_x, 5);
308 let ccv = cbpi.is_coded(mb_x, 5);
309 let q = cbpi.get_q(mb_w + mb_x);
310 let str = if q < 32 { FILTER_STRENGTH[q as usize] } else { 0 };
311 if ctu && ccu { deblock_hor(buf, 1, str, offu + mb_x * 8); }
312 if ctv && ccv { deblock_hor(buf, 2, str, offv + mb_x * 8); }
314 let mut leftu = false;
315 let mut leftv = false;
316 let offu = buf.get_offset(1) + (mb_y - 1) * 8 * strideu;
317 let offv = buf.get_offset(2) + (mb_y - 1) * 8 * stridev;
318 for mb_x in 0..mb_w {
319 let ctu = cbpi.is_coded_top(mb_x, 4);
320 let ctv = cbpi.is_coded_top(mb_x, 5);
321 let qt = cbpi.get_q(mb_x);
322 let strt = if qt < 32 { FILTER_STRENGTH[qt as usize] } else { 0 };
323 if leftu && ctu { deblock_ver(buf, 1, strt, offu + mb_x * 8); }
324 if leftv && ctv { deblock_ver(buf, 2, strt, offv + mb_x * 8); }
332 fn check_marker<'a>(br: &mut BitReader<'a>) -> DecoderResult<()> {
333 let mark = br.read(1)?;
334 validate!(mark == 1);
338 impl<'a> Intel263BR<'a> {
339 fn new(src: &'a [u8], tables: &'a Tables) -> Self {
341 br: BitReader::new(src, BitReaderMode::BE),
350 fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
351 let br = &mut self.br;
354 let mut dc = br.read(8)?;
355 if dc == 255 { dc = 128; }
356 blk[0] = (dc as i16) << 3;
359 if !coded { return Ok(()); }
361 let rl_cb = &self.tables.rl_cb; // could be aic too
362 let q_add = if quant == 0 { 0i16 } else { i16::from((quant - 1) | 1) };
363 let q = i16::from(quant * 2);
365 let code = br.read_cb(rl_cb)?;
369 if !code.is_escape() {
370 run = code.get_run();
371 level = code.get_level();
372 last = code.is_last();
373 if br.read_bool()? { level = -level; }
375 level = (level * q) + q_add;
377 level = (level * q) - q_add;
380 last = br.read_bool()?;
381 run = br.read(6)? as u8;
382 level = br.read_s(8)? as i16;
384 let low = br.read(5)? as i16;
385 let top = br.read_s(6)? as i16;
386 level = (top << 5) | low;
389 level = (level * q) + q_add;
391 level = (level * q) - q_add;
393 if level < -2048 { level = -2048; }
394 if level > 2047 { level = 2047; }
398 let oidx = ZIGZAG[idx as usize];
407 fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<i16> {
408 let code = i16::from(br.read_cb(mv_cb)?);
409 if code == 0 { return Ok(0) }
410 if !br.read_bool()? {
417 fn decode_mv(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<MV> {
418 let xval = decode_mv_component(br, mv_cb)?;
419 let yval = decode_mv_component(br, mv_cb)?;
420 Ok(MV::new(xval, yval))
423 fn decode_b_info(br: &mut BitReader, is_pb: bool, is_ipb: bool, is_intra: bool) -> DecoderResult<BBlockInfo> {
424 if is_pb { // as improved pb
426 let pb_mv_add = if is_intra { 1 } else { 0 };
429 let pb_mv_count = 1 - (br.read(1)? as usize);
430 let cbpb = br.read(6)? as u8;
431 Ok(BBlockInfo::new(true, cbpb, pb_mv_count + pb_mv_add, pb_mv_count == 1))
433 Ok(BBlockInfo::new(true, 0, 1 + pb_mv_add, true))
436 Ok(BBlockInfo::new(true, 0, pb_mv_add, false))
439 let mvdb = br.read_bool()?;
440 let cbpb = if mvdb && br.read_bool()? { br.read(6)? as u8 } else { 0 };
441 Ok(BBlockInfo::new(true, cbpb, if mvdb { 1 } else { 0 }, false))
444 Ok(BBlockInfo::new(false, 0, 0, false))
448 impl<'a> BlockDecoder for Intel263BR<'a> {
450 #[allow(unused_variables)]
451 #[allow(clippy::unreadable_literal)]
452 fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
453 let br = &mut self.br;
454 let syncw = br.read(22)?;
455 validate!(syncw == 0x000020);
456 let tr = (br.read(8)? << 8) as u16;
458 let id = br.read(1)?;
460 br.read(1)?; // split screen indicator
461 br.read(1)?; // document camera indicator
462 br.read(1)?; // freeze picture release
463 let mut sfmt = br.read(3)?;
464 validate!((sfmt != 0b000) && (sfmt != 0b110));
465 let is_intra = !br.read_bool()?;
466 let umv = br.read_bool()?;
467 br.read(1)?; // syntax arithmetic coding
468 let apm = br.read_bool()?;
469 self.is_pb = br.read_bool()?;
474 validate!((sfmt != 0b000) && (sfmt != 0b111));
475 br.read(2)?; // unknown flags
476 deblock = br.read_bool()?;
477 br.read(1)?; // unknown flag
478 pbplus = br.read_bool()?;
479 br.read(5)?; // unknown flags
480 let marker = br.read(5)?;
481 validate!(marker == 1);
486 self.is_ipb = pbplus;
489 let par = br.read(4)?;
490 w = ((br.read(9)? + 1) * 4) as usize;
492 h = ((br.read(9)? + 1) * 4) as usize;
494 let pixw = br.read(8)?;
495 let pixh = br.read(8)?;
496 validate!((pixw != 0) && (pixh != 0));
499 let (w_, h_) = H263_SIZES[sfmt as usize];
503 let quant = br.read(5)?;
504 let cpm = br.read_bool()?;
509 let trb = br.read(3)?;
510 let dbquant = br.read(2)?;
511 pbinfo = Some(PBInfo::new(trb as u8, dbquant as u8, pbplus));
515 while br.read_bool()? { // skip PEI
518 //println!("frame {}x{} intra: {} q {} pb {} apm {} umv {} @{}", w, h, is_intra, quant, self.is_pb, apm, umv, br.tell());
520 self.mb_w = (w + 15) >> 4;
522 let ftype = if is_intra { Type::I } else { Type::P };
523 let plusinfo = if deblock { Some(PlusInfo::new(false, deblock, false, false)) } else { None };
524 let mvmode = if umv { MVMode::UMV } else { MVMode::Old };
525 let picinfo = PicInfo::new(w, h, ftype, mvmode, umv, apm, quant as u8, tr, pbinfo, plusinfo);
529 #[allow(unused_variables)]
530 fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<SliceInfo> {
531 let br = &mut self.br;
532 let gbsc = br.read(17)?;
533 validate!(gbsc == 1);
534 let gn = br.read(5)?;
535 let gfid = br.read(2)?;
536 let gquant = br.read(5)?;
537 //println!("GOB gn {:X} id {} q {}", gn, gfid, gquant);
538 let ret = SliceInfo::new_gob(0, self.gob_no, gquant as u8);
543 #[allow(unused_variables)]
544 fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, sstate: &SliceState) -> DecoderResult<BlockInfo> {
545 let br = &mut self.br;
546 let mut q = slice.get_quant();
547 match info.get_mode() {
549 let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?;
550 while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; }
551 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
552 let cbp = (cbpy << 2) | (cbpc & 3);
553 let dquant = (cbpc & 4) != 0;
555 let idx = br.read(2)? as usize;
556 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
558 Ok(BlockInfo::new(Type::I, cbp, q))
561 if br.read_bool()? { return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant())); }
562 let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?;
563 while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; }
564 let is_intra = (cbpc & 0x04) != 0;
565 let dquant = (cbpc & 0x08) != 0;
566 let is_4x4 = (cbpc & 0x10) != 0;
568 let mut mvec: Vec<MV> = Vec::new();
569 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, true)?;
570 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
571 let cbp = (cbpy << 2) | (cbpc & 3);
573 let idx = br.read(2)? as usize;
574 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
576 let mut binfo = BlockInfo::new(Type::I, cbp, q);
577 binfo.set_bpart(bbinfo);
579 for _ in 0..bbinfo.get_num_mv() {
580 mvec.push(decode_mv(br, &self.tables.mv_cb)?);
582 binfo.set_b_mv(mvec.as_slice());
587 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, false)?;
588 let mut cbpy = br.read_cb(&self.tables.cbpy_cb)?;
589 // if /* !aiv && */(cbpc & 3) != 3 {
592 let cbp = (cbpy << 2) | (cbpc & 3);
594 let idx = br.read(2)? as usize;
595 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
597 let mut binfo = BlockInfo::new(Type::P, cbp, q);
598 binfo.set_bpart(bbinfo);
600 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
603 let mvec: [MV; 4] = [
604 decode_mv(br, &self.tables.mv_cb)?,
605 decode_mv(br, &self.tables.mv_cb)?,
606 decode_mv(br, &self.tables.mv_cb)?,
607 decode_mv(br, &self.tables.mv_cb)?
612 let mut mvec: Vec<MV> = Vec::with_capacity(bbinfo.get_num_mv());
613 for _ in 0..bbinfo.get_num_mv() {
614 let mv = decode_mv(br, &self.tables.mv_cb)?;
617 binfo.set_b_mv(mvec.as_slice());
621 _ => { Err(DecoderError::InvalidData) },
625 #[allow(unused_variables)]
626 fn decode_block_intra(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
627 self.decode_block(quant, true, coded, blk)
630 #[allow(unused_variables)]
631 fn decode_block_inter(&mut self, info: &BlockInfo, sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
632 self.decode_block(quant, false, coded, blk)
635 fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
638 impl Intel263Decoder {
640 let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
641 let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
642 let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
643 let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
644 let mut coderead = H263ShortCodeReader::new(H263_CBPY);
645 let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
646 let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
647 let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
648 let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC);
649 let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
650 let mut coderead = H263ShortCodeReader::new(H263_MV);
651 let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
652 let tables = Tables {
662 info: NACodecInfo::new_dummy(),
663 dec: H263BaseDecoder::new(true),
665 bdsp: I263BlockDSP::default(),
672 impl NADecoder for Intel263Decoder {
673 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
674 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
675 let w = vinfo.get_width();
676 let h = vinfo.get_height();
677 let fmt = formats::YUV420_FORMAT;
678 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
679 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
682 Err(DecoderError::InvalidData)
685 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
686 let src = pkt.get_buffer();
691 if self.lastframe.is_none() {
692 buftype = NABufferType::None;
693 ftype = FrameType::Skip;
696 std::mem::swap(&mut self.lastframe, &mut buf);
697 buftype = buf.unwrap();
698 ftype = FrameType::B;
700 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
701 frm.set_keyframe(false);
702 frm.set_frame_type(ftype);
703 if self.lastpts.is_some() {
704 frm.set_pts(self.lastpts);
707 return Ok(frm.into_ref());
709 let mut ibr = Intel263BR::new(&src, &self.tables);
711 let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?;
713 let mut cur_pts = pkt.get_pts();
714 if !self.dec.is_intra() {
715 let bret = self.dec.get_bframe(&self.bdsp);
716 if let Ok(b_buf) = bret {
717 self.lastframe = Some(b_buf);
718 self.lastpts = pkt.get_pts();
719 if let Some(pts) = pkt.get_pts() {
720 cur_pts = Some(pts + 1);
725 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
726 frm.set_keyframe(self.dec.is_intra());
727 frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
728 frm.set_pts(cur_pts);
731 fn flush(&mut self) {
736 impl NAOptionHandler for Intel263Decoder {
737 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
738 fn set_options(&mut self, _options: &[NAOption]) { }
739 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
743 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
744 Box::new(Intel263Decoder::new())
749 use nihav_core::codecs::RegisteredDecoders;
750 use nihav_core::demuxers::RegisteredDemuxers;
751 use nihav_codec_support::test::dec_video::*;
752 use crate::indeo_register_all_decoders;
753 use nihav_commonfmt::generic_register_all_demuxers;
756 let mut dmx_reg = RegisteredDemuxers::new();
757 generic_register_all_demuxers(&mut dmx_reg);
758 let mut dec_reg = RegisteredDecoders::new();
759 indeo_register_all_decoders(&mut dec_reg);
761 // sample: https://samples.mplayerhq.hu/A-codecs/IMC/neal73_saber.avi
762 test_decoding("avi", "intel263", "assets/Indeo/neal73_saber.avi", Some(16),
763 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
764 [0x698c4f70, 0xf727bfc1, 0x96e687e9, 0xc9e37073],
765 [0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e],
766 [0x95dfe457, 0xaaeeaca9, 0x9764c111, 0xdf055b1f],
767 [0xac1d708c, 0x8e34aa47, 0x240b8f0e, 0x797b052b],
768 [0x965fe621, 0xebb049da, 0x18345724, 0x748ea32f],
769 [0x126c7492, 0x54d7457f, 0x9968a723, 0x89629378],
770 [0x8c690125, 0x3de8da89, 0x6030b702, 0xbd3f09ab],
771 [0xa9d3f7c7, 0xdfa1795c, 0x7ed34e86, 0x58b7cc26],
772 [0xe500e50e, 0x2312197d, 0xb8e93f41, 0xe6890cd8],
773 [0x2e8d8f15, 0xaf1c84fe, 0x05fec093, 0x3c383abb],
774 [0x6a1def4b, 0xc3549acc, 0x9ed127be, 0x2872f751],
775 [0x36599508, 0xe169caf9, 0xcdf6af6b, 0x29d167b8],
776 [0xfe98869d, 0x2b16b94b, 0x97caaf72, 0xbf7cc0c1],
777 [0x9fbfaf0a, 0xfa4ce8fc, 0xdc038ab8, 0x649c1eaa],
778 [0x141749be, 0xfba7acd4, 0xd0372e02, 0x6b191bc5],
779 [0x99252b73, 0x2ce009d9, 0xf6753c1d, 0x31892a08],
780 [0xefe81436, 0x4ab365db, 0x57a0b058, 0x26a6ca02]]));