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::*;
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>,
23 struct VivoBlockDSP {}
25 impl VivoBlockDSP { fn new() -> Self { Self {} } }
27 #[allow(clippy::erasing_op)]
28 #[allow(clippy::identity_op)]
29 fn deblock_hor(buf: &mut [u8], off: usize, stride: usize, clip_tab: &[i16; 64]) {
31 let p1 = i16::from(buf[off - 2 * stride + x]);
32 let p0 = i16::from(buf[off - 1 * stride + x]);
33 let q0 = i16::from(buf[off + 0 * stride + x]);
34 let q1 = i16::from(buf[off + 1 * stride + x]);
35 let diff = (3 * (p1 - q1) + 8 * (q0 - p0)) >> 4;
36 if (diff != 0) && (diff > -32) && (diff < 32) {
37 let delta = clip_tab[(diff + 32) as usize];
38 buf[off - 1 * stride + x] = (p0 + delta).max(0).min(255) as u8;
39 buf[off + 0 * stride + x] = (q0 - delta).max(0).min(255) as u8;
44 #[allow(clippy::identity_op)]
45 fn deblock_ver(buf: &mut [u8], off: usize, stride: usize, clip_tab: &[i16; 64]) {
47 let p1 = i16::from(buf[off - 2 + y * stride]);
48 let p0 = i16::from(buf[off - 1 + y * stride]);
49 let q0 = i16::from(buf[off + 0 + y * stride]);
50 let q1 = i16::from(buf[off + 1 + y * stride]);
51 let diff = (3 * (p1 - q1) + 8 * (q0 - p0)) >> 4;
52 if (diff != 0) && (diff > -32) && (diff < 32) {
53 let delta = clip_tab[(diff + 32) as usize];
54 buf[off - 1 + y * stride] = (p0 + delta).max(0).min(255) as u8;
55 buf[off + y * stride] = (q0 - delta).max(0).min(255) as u8;
60 fn gen_clip_tab(clip_tab: &mut [i16; 64], q: u8) {
63 let lim = (q + 2) >> 1;
65 clip_tab[(32 - i) as usize] = -i;
66 clip_tab[(32 + i) as usize] = i;
70 clip_tab[(32 - i) as usize] = -val;
71 clip_tab[(32 + i) as usize] = val;
75 impl BlockDSP for VivoBlockDSP {
76 fn idct(&self, blk: &mut [i16; 64]) {
77 h263_annex_w_idct(blk);
79 fn copy_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
80 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
81 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
83 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
85 blockdsp::copy_block(&mut dst, src.clone(), 0, xpos, ypos, mv.x >> 1, mv.y >> 1, 16, 16, 0, 1, mode, H263_INTERP_FUNCS);
86 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);
87 blockdsp::copy_block(&mut dst, src.clone(), 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_FUNCS);
89 fn copy_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
90 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
93 let xadd = (i & 1) * 8;
94 let yadd = (i & 2) * 4;
95 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
97 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);
100 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
101 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
102 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
103 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
105 blockdsp::copy_block(&mut dst, src.clone(), plane, xpos >> 1, ypos >> 1, cmx >> 1, cmy >> 1, 8, 8, 0, 1, mode, H263_INTERP_FUNCS);
108 fn avg_blocks(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mv: MV) {
109 let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
110 let cmode = (if (mv.x & 3) != 0 { 1 } else { 0 }) + (if (mv.y & 3) != 0 { 2 } else { 0 });
112 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
114 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);
115 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);
116 blockdsp::copy_block(&mut dst, src.clone(), 2, xpos >> 1, ypos >> 1, mv.x >> 2, mv.y >> 2, 8, 8, 0, 1, cmode, H263_INTERP_AVG_FUNCS);
118 fn avg_blocks8x8(&self, dst: &mut NAVideoBuffer<u8>, src: NAVideoBufferRef<u8>, xpos: usize, ypos: usize, mvs: &[MV; 4]) {
119 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
122 let xadd = (i & 1) * 8;
123 let yadd = (i & 2) * 4;
124 let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize;
126 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);
129 let sum_mv = mvs[0] + mvs[1] + mvs[2] + mvs[3];
130 let cmx = (sum_mv.x >> 3) + H263_CHROMA_ROUND[(sum_mv.x & 0xF) as usize];
131 let cmy = (sum_mv.y >> 3) + H263_CHROMA_ROUND[(sum_mv.y & 0xF) as usize];
132 let mode = ((cmx & 1) + (cmy & 1) * 2) as usize;
134 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);
137 fn filter_row(&self, buf: &mut NAVideoBuffer<u8>, mb_y: usize, mb_w: usize, cbpi: &CBPInfo) {
138 let ystride = buf.get_stride(0);
139 let ustride = buf.get_stride(1);
140 let vstride = buf.get_stride(2);
141 let yoff = buf.get_offset(0) + mb_y * 16 * ystride;
142 let uoff = buf.get_offset(1) + mb_y * 8 * ustride;
143 let voff = buf.get_offset(2) + mb_y * 8 * vstride;
144 let buf = buf.get_data_mut().unwrap();
146 let mut clip_tab = [0i16; 64];
149 for mb_x in 0..mb_w {
151 let coded0 = cbpi.is_coded(mb_x, 0);
152 let coded1 = cbpi.is_coded(mb_x, 1);
153 let q = cbpi.get_q(mb_w + mb_x);
155 gen_clip_tab(&mut clip_tab, q);
159 if coded0 && cbpi.is_coded_top(mb_x, 0) {
160 deblock_hor(buf, ystride, coff, &clip_tab);
162 if coded1 && cbpi.is_coded_top(mb_x, 1) {
163 deblock_hor(buf, ystride, coff + 8, &clip_tab);
166 let coff = off + 8 * ystride;
167 if cbpi.is_coded(mb_x, 2) && coded0 {
168 deblock_hor(buf, ystride, coff, &clip_tab);
170 if cbpi.is_coded(mb_x, 3) && coded1 {
171 deblock_hor(buf, ystride, coff + 8, &clip_tab);
175 let mut leftt = false;
176 let mut leftc = false;
178 for mb_x in 0..mb_w {
179 let ctop0 = cbpi.is_coded_top(mb_x, 0);
180 let ctop1 = cbpi.is_coded_top(mb_x, 0);
181 let ccur0 = cbpi.is_coded(mb_x, 0);
182 let ccur1 = cbpi.is_coded(mb_x, 1);
183 let q = cbpi.get_q(mb_w + mb_x);
185 gen_clip_tab(&mut clip_tab, q);
189 let coff = off - 8 * ystride;
190 let qtop = cbpi.get_q(mb_x);
192 gen_clip_tab(&mut clip_tab, qtop);
196 deblock_ver(buf, ystride, coff, &clip_tab);
199 deblock_ver(buf, ystride, coff + 8, &clip_tab);
203 deblock_ver(buf, ystride, off, &clip_tab);
206 deblock_ver(buf, ystride, off + 8, &clip_tab);
213 for mb_x in 0..mb_w {
214 let ctu = cbpi.is_coded_top(mb_x, 4);
215 let ccu = cbpi.is_coded(mb_x, 4);
216 let ctv = cbpi.is_coded_top(mb_x, 5);
217 let ccv = cbpi.is_coded(mb_x, 5);
218 let q = cbpi.get_q(mb_w + mb_x);
220 gen_clip_tab(&mut clip_tab, q);
224 deblock_hor(buf, ustride, uoff + mb_x * 8, &clip_tab);
227 deblock_hor(buf, vstride, voff + mb_x * 8, &clip_tab);
230 let mut leftu = false;
231 let mut leftv = false;
232 let offu = uoff - 8 * ustride;
233 let offv = voff - 8 * vstride;
234 for mb_x in 0..mb_w {
235 let ctu = cbpi.is_coded_top(mb_x, 4);
236 let ctv = cbpi.is_coded_top(mb_x, 5);
237 let qt = cbpi.get_q(mb_x);
239 gen_clip_tab(&mut clip_tab, qt);
243 deblock_ver(buf, ustride, offu + mb_x * 8, &clip_tab);
246 deblock_ver(buf, vstride, offv + mb_x * 8, &clip_tab);
256 info: NACodecInfoRef,
257 dec: H263BaseDecoder,
260 lastframe: Option<NABufferType>,
261 lastpts: Option<u64>,
278 fn check_marker<'a>(br: &mut BitReader<'a>) -> DecoderResult<()> {
279 let mark = br.read(1)?;
280 validate!(mark == 1);
284 impl<'a> VivoBR<'a> {
285 fn new(src: &'a [u8], tables: &'a Tables, ref_w: usize, ref_h: usize) -> Self {
287 br: BitReader::new(src, BitReaderMode::BE),
298 fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], _plane_no: usize, acpred: ACPredMode) -> DecoderResult<()> {
299 let br = &mut self.br;
301 if !self.aic && intra {
302 let mut dc = br.read(8)? as i16;
303 if dc == 255 { dc = 128; }
307 if !coded { return Ok(()); }
308 let scan = match acpred {
309 ACPredMode::Hor => H263_SCAN_V,
310 ACPredMode::Ver => H263_SCAN_H,
314 let rl_cb = if self.aic && intra { &self.tables.aic_rl_cb } else { &self.tables.rl_cb };
315 let q = i16::from(quant * 2);
316 let q_add = if q == 0 || self.aic { 0i16 } else { (((q >> 1) - 1) | 1) as i16 };
318 let code = br.read_cb(rl_cb)?;
322 if !code.is_escape() {
323 run = code.get_run();
324 level = code.get_level();
325 last = code.is_last();
326 if br.read_bool()? { level = -level; }
327 if !intra || idx != 0 {
329 level = (level * q) + q_add;
331 level = (level * q) - q_add;
335 last = br.read_bool()?;
336 run = br.read(6)? as u8;
337 level = br.read_s(8)? as i16;
339 let low = br.read(5)? as i16;
340 let top = br.read_s(6)? as i16;
341 level = (top << 5) | low;
343 if !intra || idx != 0 {
345 level = (level * q) + q_add;
347 level = (level * q) - q_add;
349 if level < -2048 { level = -2048; }
350 if level > 2047 { level = 2047; }
355 let oidx = scan[idx as usize];
364 fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<i16> {
365 let code = i16::from(br.read_cb(mv_cb)?);
366 if code == 0 { return Ok(0) }
367 if !br.read_bool()? {
374 fn decode_mv(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<MV> {
375 let xval = decode_mv_component(br, mv_cb)?;
376 let yval = decode_mv_component(br, mv_cb)?;
377 Ok(MV::new(xval, yval))
380 fn decode_b_info(br: &mut BitReader, is_pb: bool, is_ipb: bool, is_intra: bool) -> DecoderResult<BBlockInfo> {
381 if is_pb { // as improved pb
383 let pb_mv_add = if is_intra { 1 } else { 0 };
386 let pb_mv_count = 1 - (br.read(1)? as usize);
387 let cbpb = br.read(6)? as u8;
388 Ok(BBlockInfo::new(true, cbpb, pb_mv_count + pb_mv_add, pb_mv_count == 1))
390 Ok(BBlockInfo::new(true, 0, 1 + pb_mv_add, true))
393 Ok(BBlockInfo::new(true, 0, pb_mv_add, false))
396 let mvdb = br.read_bool()?;
397 let cbpb = if mvdb && br.read_bool()? { br.read(6)? as u8 } else { 0 };
398 Ok(BBlockInfo::new(true, cbpb, if mvdb { 1 } else { 0 }, false))
401 Ok(BBlockInfo::new(false, 0, 0, false))
405 impl<'a> BlockDecoder for VivoBR<'a> {
407 #[allow(unused_variables)]
408 #[allow(clippy::unreadable_literal)]
409 fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
410 let br = &mut self.br;
411 let syncw = br.read(22)?;
412 validate!(syncw == 0x000020);
413 let tr = (br.read(8)? << 8) as u16;
415 let id = br.read(1)?;
417 br.read(1)?; // split screen indicator
418 br.read(1)?; // document camera indicator
419 br.read(1)?; // freeze picture release
420 let mut sfmt = br.read(3)?;
421 validate!(sfmt != 0b000);
422 let is_intra = !br.read_bool()?;
423 let umv = br.read_bool()?;
424 br.read(1)?; // syntax arithmetic coding
425 let apm = br.read_bool()?;
426 self.is_pb = br.read_bool()?;
432 validate!(sfmt != 0b000 && sfmt != 0b110);
433 aic = br.read_bool()?;
434 br.read(1)?; // umv mode
435 deblock = br.read_bool()?;
436 br.read(3)?; // unknown flags
437 pbplus = br.read_bool()?;
438 br.read(4)?; // unknown flags
444 self.is_ipb = pbplus;
445 let (w, h) = match sfmt {
452 validate!((self.ref_w != 0) && (self.ref_h != 0));
453 ((self.ref_w + 15) & !15, (self.ref_h + 15) & !15)
455 _ => return Err(DecoderError::InvalidData),
457 let quant = br.read(5)?;
458 let cpm = br.read_bool()?;
463 let trb = br.read(3)?;
464 let dbquant = br.read(2)?;
465 pbinfo = Some(PBInfo::new(trb as u8, dbquant as u8, pbplus));
469 while br.read_bool()? { // skip PEI
473 self.mb_w = (w + 15) >> 4;
476 let ftype = if is_intra { Type::I } else { Type::P };
477 let plusinfo = Some(PlusInfo::new(aic, deblock, false, false));
478 let mvmode = if umv { MVMode::UMV } else { MVMode::Old };
479 let picinfo = PicInfo::new(w, h, ftype, mvmode, umv, apm, quant as u8, tr, pbinfo, plusinfo);
483 #[allow(unused_variables)]
484 fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<SliceInfo> {
485 let br = &mut self.br;
486 let gbsc = br.read(17)?;
487 validate!(gbsc == 1);
488 let gn = br.read(5)?;
489 let gfid = br.read(2)?;
490 let gquant = br.read(5)?;
491 let ret = SliceInfo::new_gob(0, self.gob_no, gquant as u8);
496 #[allow(unused_variables)]
497 fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, sstate: &SliceState) -> DecoderResult<BlockInfo> {
498 let br = &mut self.br;
499 let mut q = slice.get_quant();
500 match info.get_mode() {
502 let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?;
503 while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; }
504 let mut acpred = ACPredMode::None;
505 if let Some(ref pi) = info.plusinfo {
507 let acpp = br.read_bool()?;
508 acpred = ACPredMode::DC;
510 acpred = if !br.read_bool()? { ACPredMode::Hor } else { ACPredMode::Ver };
514 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
515 let cbp = (cbpy << 2) | (cbpc & 3);
516 let dquant = (cbpc & 4) != 0;
518 let idx = br.read(2)? as usize;
519 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
521 let mut binfo = BlockInfo::new(Type::I, cbp, q);
522 binfo.set_acpred(acpred);
526 if br.read_bool()? { return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant())); }
527 let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?;
528 while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; }
529 let is_intra = (cbpc & 0x04) != 0;
530 let dquant = (cbpc & 0x08) != 0;
531 let is_4x4 = (cbpc & 0x10) != 0;
533 let mut acpred = ACPredMode::None;
534 if let Some(ref pi) = info.plusinfo {
536 let acpp = br.read_bool()?;
537 acpred = ACPredMode::DC;
539 acpred = if !br.read_bool()? { ACPredMode::Hor } else { ACPredMode::Ver };
543 let mut mvec: Vec<MV> = Vec::new();
544 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, true)?;
545 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
546 let cbp = (cbpy << 2) | (cbpc & 3);
548 let idx = br.read(2)? as usize;
549 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
551 let mut binfo = BlockInfo::new(Type::I, cbp, q);
552 binfo.set_bpart(bbinfo);
553 binfo.set_acpred(acpred);
555 for _ in 0..bbinfo.get_num_mv() {
556 mvec.push(decode_mv(br, &self.tables.mv_cb)?);
558 binfo.set_b_mv(mvec.as_slice());
563 let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, false)?;
564 let mut cbpy = br.read_cb(&self.tables.cbpy_cb)?;
565 // if /* !aiv && */(cbpc & 3) != 3 {
568 let cbp = (cbpy << 2) | (cbpc & 3);
570 let idx = br.read(2)? as usize;
571 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
573 let mut binfo = BlockInfo::new(Type::P, cbp, q);
574 binfo.set_bpart(bbinfo);
576 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
579 let mvec: [MV; 4] = [
580 decode_mv(br, &self.tables.mv_cb)?,
581 decode_mv(br, &self.tables.mv_cb)?,
582 decode_mv(br, &self.tables.mv_cb)?,
583 decode_mv(br, &self.tables.mv_cb)?
588 let mut mvec: Vec<MV> = Vec::with_capacity(bbinfo.get_num_mv());
589 for _ in 0..bbinfo.get_num_mv() {
590 let mv = decode_mv(br, &self.tables.mv_cb)?;
593 binfo.set_b_mv(mvec.as_slice());
597 _ => Err(DecoderError::InvalidData),
601 #[allow(unused_variables)]
602 fn decode_block_intra(&mut self, info: &BlockInfo, _sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
603 self.decode_block(quant, true, coded, blk, if no < 4 { 0 } else { no - 3 }, info.get_acpred())
606 #[allow(unused_variables)]
607 fn decode_block_inter(&mut self, info: &BlockInfo, _sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
608 self.decode_block(quant, false, coded, blk, if no < 4 { 0 } else { no - 3 }, ACPredMode::None)
611 fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
616 let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
617 let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
618 let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
619 let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
620 let mut coderead = H263ShortCodeReader::new(H263_CBPY);
621 let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
622 let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
623 let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
624 let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC);
625 let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
626 let mut coderead = H263ShortCodeReader::new(H263_MV);
627 let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
628 let tables = Tables {
638 info: NACodecInfo::new_dummy(),
639 dec: H263BaseDecoder::new_with_opts(H263DEC_OPT_SLICE_RESET | H263DEC_OPT_USES_GOB | H263DEC_OPT_PRED_QUANT),
641 bdsp: VivoBlockDSP::new(),
650 impl NADecoder for VivoDecoder {
651 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
652 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
653 let w = vinfo.get_width();
654 let h = vinfo.get_height();
655 let fmt = formats::YUV420_FORMAT;
656 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
657 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
662 Err(DecoderError::InvalidData)
665 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
666 let src = pkt.get_buffer();
671 if self.lastframe.is_none() {
672 buftype = NABufferType::None;
673 ftype = FrameType::Skip;
676 std::mem::swap(&mut self.lastframe, &mut buf);
677 buftype = buf.unwrap();
678 ftype = FrameType::B;
680 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
681 frm.set_keyframe(false);
682 frm.set_frame_type(ftype);
683 if self.lastpts.is_some() {
684 frm.set_pts(self.lastpts);
687 return Ok(frm.into_ref());
689 let mut ibr = VivoBR::new(&src, &self.tables, self.width, self.height);
691 let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?;
693 let mut cur_pts = pkt.get_pts();
694 if !self.dec.is_intra() {
695 let bret = self.dec.get_bframe(&self.bdsp);
696 if let Ok(b_buf) = bret {
697 self.lastframe = Some(b_buf);
698 self.lastpts = pkt.get_pts();
699 if let Some(pts) = pkt.get_pts() {
700 cur_pts = Some(pts + 1);
705 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
706 frm.set_keyframe(self.dec.is_intra());
707 frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
708 frm.set_pts(cur_pts);
711 fn flush(&mut self) {
716 impl NAOptionHandler for VivoDecoder {
717 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
718 fn set_options(&mut self, _options: &[NAOption]) { }
719 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
723 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
724 Box::new(VivoDecoder::new())
729 use nihav_core::codecs::RegisteredDecoders;
730 use nihav_core::demuxers::RegisteredDemuxers;
731 use nihav_codec_support::test::dec_video::*;
732 use crate::vivo_register_all_decoders;
733 use crate::vivo_register_all_demuxers;
736 let mut dmx_reg = RegisteredDemuxers::new();
737 vivo_register_all_demuxers(&mut dmx_reg);
738 let mut dec_reg = RegisteredDecoders::new();
739 vivo_register_all_decoders(&mut dec_reg);
741 test_file_decoding("vivo", "assets/Misc/gr_al.viv", Some(16), true, false, Some("viv1"), &dmx_reg, &dec_reg);
742 // test_decoding("vivo", "vivo1", "assets/Misc/gr_al.viv", Some(16),
743 // &dmx_reg, &dec_reg, ExpectedTestResult::GenerateMD5Frames));
747 let mut dmx_reg = RegisteredDemuxers::new();
748 vivo_register_all_demuxers(&mut dmx_reg);
749 let mut dec_reg = RegisteredDecoders::new();
750 vivo_register_all_decoders(&mut dec_reg);
752 test_file_decoding("vivo", "assets/Misc/02-KimagureOrangeRoad.viv", Some(50), true, false, Some("viv2"), &dmx_reg, &dec_reg);
754 // test_decoding("vivo", "vivo2", "assets/Misc/greetings.viv", Some(16),
755 // &dmx_reg, &dec_reg, ExpectedTestResult::GenerateMD5Frames));