vivo: improve decoding
[nihav.git] / nihav-vivo / src / codecs / vivo.rs
CommitLineData
31cf33ac
KS
1use nihav_core::io::bitreader::*;
2use nihav_core::io::codebook::*;
3use nihav_core::formats;
4use nihav_core::frame::*;
5use nihav_core::codecs::*;
6use nihav_codec_support::codecs::{MV, ZIGZAG};
2af66d55 7use nihav_codec_support::codecs::blockdsp;
31cf33ac 8use nihav_codec_support::codecs::h263::*;
2af66d55 9use nihav_codec_support::codecs::h263::code::*;
31cf33ac
KS
10use nihav_codec_support::codecs::h263::decoder::*;
11use nihav_codec_support::codecs::h263::data::*;
12
13#[allow(dead_code)]
14struct Tables {
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>,
20 mv_cb: Codebook<u8>,
21}
22
2af66d55
KS
23struct VivoBlockDSP {}
24
25impl VivoBlockDSP { fn new() -> Self { Self {} } }
26
27#[allow(clippy::erasing_op)]
28#[allow(clippy::identity_op)]
29fn deblock_hor(buf: &mut [u8], off: usize, stride: usize, clip_tab: &[i16; 64]) {
30 for x in 0..8 {
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;
40 }
41 }
42}
43
44#[allow(clippy::identity_op)]
45fn deblock_ver(buf: &mut [u8], off: usize, stride: usize, clip_tab: &[i16; 64]) {
46 for y in 0..8 {
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;
56 }
57 }
58}
59
60fn gen_clip_tab(clip_tab: &mut [i16; 64], q: u8) {
61 let q = i16::from(q);
62 *clip_tab = [0; 64];
63 let lim = (q + 2) >> 1;
64 for i in 0..lim {
65 clip_tab[(32 - i) as usize] = -i;
66 clip_tab[(32 + i) as usize] = i;
67 }
68 for i in lim..q {
69 let val = q - i;
70 clip_tab[(32 - i) as usize] = -val;
71 clip_tab[(32 + i) as usize] = val;
72 }
73}
74
75impl BlockDSP for VivoBlockDSP {
76 fn idct(&self, blk: &mut [i16; 64]) {
77 h263_annex_w_idct(blk);
78 }
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 });
82
83 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
84
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);
88 }
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();
91
92 for i in 0..4 {
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;
96
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);
98 }
99
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;
104 for plane in 1..3 {
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);
106 }
107 }
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 });
111
112 let mut dst = NASimpleVideoFrame::from_video_buf(dst).unwrap();
113
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);
117 }
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();
120
121 for i in 0..4 {
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;
125
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);
127 }
128
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;
133 for plane in 1..3 {
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);
135 }
136 }
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();
145
146 let mut clip_tab = [0i16; 64];
147 let mut last_q = 0;
148 let mut off = yoff;
149 for mb_x in 0..mb_w {
150 let coff = off;
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);
154 if q != last_q {
155 gen_clip_tab(&mut clip_tab, q);
156 last_q = q;
157 }
158 if mb_y != 0 {
159 if coded0 && cbpi.is_coded_top(mb_x, 0) {
160 deblock_hor(buf, ystride, coff, &clip_tab);
161 }
162 if coded1 && cbpi.is_coded_top(mb_x, 1) {
163 deblock_hor(buf, ystride, coff + 8, &clip_tab);
164 }
165 }
166 let coff = off + 8 * ystride;
167 if cbpi.is_coded(mb_x, 2) && coded0 {
168 deblock_hor(buf, ystride, coff, &clip_tab);
169 }
170 if cbpi.is_coded(mb_x, 3) && coded1 {
171 deblock_hor(buf, ystride, coff + 8, &clip_tab);
172 }
173 off += 16;
174 }
175 let mut leftt = false;
176 let mut leftc = false;
177 let mut off = yoff;
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);
184 if q != last_q {
185 gen_clip_tab(&mut clip_tab, q);
186 last_q = q;
187 }
188 if mb_y != 0 {
189 let coff = off - 8 * ystride;
190 let qtop = cbpi.get_q(mb_x);
191 if qtop != last_q {
192 gen_clip_tab(&mut clip_tab, qtop);
193 last_q = qtop;
194 }
195 if leftt && ctop0 {
196 deblock_ver(buf, ystride, coff, &clip_tab);
197 }
198 if ctop0 && ctop1 {
199 deblock_ver(buf, ystride, coff + 8, &clip_tab);
200 }
201 }
202 if leftc && ccur0 {
203 deblock_ver(buf, ystride, off, &clip_tab);
204 }
205 if ccur0 && ccur1 {
206 deblock_ver(buf, ystride, off + 8, &clip_tab);
207 }
208 leftt = ctop1;
209 leftc = ccur1;
210 off += 16;
211 }
212 if mb_y != 0 {
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);
219 if q != last_q {
220 gen_clip_tab(&mut clip_tab, q);
221 last_q = q;
222 }
223 if ctu && ccu {
224 deblock_hor(buf, ustride, uoff + mb_x * 8, &clip_tab);
225 }
226 if ctv && ccv {
227 deblock_hor(buf, vstride, voff + mb_x * 8, &clip_tab);
228 }
229 }
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);
238 if qt != last_q {
239 gen_clip_tab(&mut clip_tab, qt);
240 last_q = qt;
241 }
242 if leftu && ctu {
243 deblock_ver(buf, ustride, offu + mb_x * 8, &clip_tab);
244 }
245 if leftv && ctv {
246 deblock_ver(buf, vstride, offv + mb_x * 8, &clip_tab);
247 }
248 leftu = ctu;
249 leftv = ctv;
250 }
251 }
252 }
253}
254
31cf33ac
KS
255struct VivoDecoder {
256 info: NACodecInfoRef,
257 dec: H263BaseDecoder,
258 tables: Tables,
2af66d55 259 bdsp: VivoBlockDSP,
31cf33ac
KS
260 lastframe: Option<NABufferType>,
261 lastpts: Option<u64>,
262 width: usize,
263 height: usize,
264}
265
266struct VivoBR<'a> {
267 br: BitReader<'a>,
268 tables: &'a Tables,
269 gob_no: usize,
270 mb_w: usize,
271 is_pb: bool,
272 is_ipb: bool,
273 ref_w: usize,
274 ref_h: usize,
275 aic: bool,
276}
277
278fn check_marker<'a>(br: &mut BitReader<'a>) -> DecoderResult<()> {
279 let mark = br.read(1)?;
280 validate!(mark == 1);
281 Ok(())
282}
283
284impl<'a> VivoBR<'a> {
285 fn new(src: &'a [u8], tables: &'a Tables, ref_w: usize, ref_h: usize) -> Self {
286 VivoBR {
287 br: BitReader::new(src, BitReaderMode::BE),
288 tables,
289 gob_no: 0,
290 mb_w: 0,
291 is_pb: false,
292 is_ipb: false,
293 ref_w, ref_h,
294 aic: false,
295 }
296 }
297
2af66d55 298 fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], _plane_no: usize, acpred: ACPredMode) -> DecoderResult<()> {
31cf33ac
KS
299 let br = &mut self.br;
300 let mut idx = 0;
301 if !self.aic && intra {
302 let mut dc = br.read(8)? as i16;
303 if dc == 255 { dc = 128; }
304 blk[0] = dc << 3;
305 idx = 1;
306 }
307 if !coded { return Ok(()); }
308 let scan = match acpred {
309 ACPredMode::Hor => H263_SCAN_V,
310 ACPredMode::Ver => H263_SCAN_H,
311 _ => &ZIGZAG,
312 };
313
314 let rl_cb = if self.aic && intra { &self.tables.aic_rl_cb } else { &self.tables.rl_cb };
2af66d55 315 let q = i16::from(quant * 2);
31cf33ac
KS
316 let q_add = if q == 0 || self.aic { 0i16 } else { (((q >> 1) - 1) | 1) as i16 };
317 while idx < 64 {
318 let code = br.read_cb(rl_cb)?;
319 let run;
320 let mut level;
321 let last;
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; }
2af66d55
KS
327 if !intra || idx != 0 {
328 if level >= 0 {
329 level = (level * q) + q_add;
330 } else {
331 level = (level * q) - q_add;
332 }
31cf33ac
KS
333 }
334 } else {
335 last = br.read_bool()?;
336 run = br.read(6)? as u8;
337 level = br.read_s(8)? as i16;
338 if level == -128 {
339 let low = br.read(5)? as i16;
340 let top = br.read_s(6)? as i16;
341 level = (top << 5) | low;
342 }
2af66d55
KS
343 if !intra || idx != 0 {
344 if level >= 0 {
345 level = (level * q) + q_add;
346 } else {
347 level = (level * q) - q_add;
348 }
349 if level < -2048 { level = -2048; }
350 if level > 2047 { level = 2047; }
31cf33ac 351 }
31cf33ac
KS
352 }
353 idx += run;
354 validate!(idx < 64);
355 let oidx = scan[idx as usize];
356 blk[oidx] = level;
357 idx += 1;
358 if last { break; }
359 }
360 Ok(())
361 }
362}
363
364fn 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()? {
368 Ok(code)
369 } else {
370 Ok(-code)
371 }
372}
373
374fn 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))
378}
379
380fn decode_b_info(br: &mut BitReader, is_pb: bool, is_ipb: bool, is_intra: bool) -> DecoderResult<BBlockInfo> {
381 if is_pb { // as improved pb
382 if is_ipb {
383 let pb_mv_add = if is_intra { 1 } else { 0 };
384 if br.read_bool()?{
385 if br.read_bool()? {
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))
389 } else {
390 Ok(BBlockInfo::new(true, 0, 1 + pb_mv_add, true))
391 }
392 } else {
393 Ok(BBlockInfo::new(true, 0, pb_mv_add, false))
394 }
395 } else {
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))
399 }
400 } else {
401 Ok(BBlockInfo::new(false, 0, 0, false))
402 }
403}
404
405impl<'a> BlockDecoder for VivoBR<'a> {
406
407#[allow(unused_variables)]
494ad253 408#[allow(clippy::unreadable_literal)]
31cf33ac
KS
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;
414 check_marker(br)?;
415 let id = br.read(1)?;
416 validate!(id == 0);
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()?;
427 let deblock;
428 let pbplus;
429 let aic;
430 if sfmt == 0b110 {
431 sfmt = br.read(3)?;
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
439 } else {
440 aic = false;
441 deblock = false;
442 pbplus = false;
443 }
444 self.is_ipb = pbplus;
445 let (w, h) = match sfmt {
446 0b001 => ( 64, 48),
447 0b011 => ( 88, 72),
448 0b010 => (176, 144),
449 0b100 => (352, 288),
450 0b101 => (704, 576),
451 0b111 => {
452 validate!((self.ref_w != 0) && (self.ref_h != 0));
453 ((self.ref_w + 15) & !15, (self.ref_h + 15) & !15)
454 },
455 _ => return Err(DecoderError::InvalidData),
456 };
457 let quant = br.read(5)?;
458 let cpm = br.read_bool()?;
459 validate!(!cpm);
460
461 let pbinfo;
462 if self.is_pb {
463 let trb = br.read(3)?;
464 let dbquant = br.read(2)?;
465 pbinfo = Some(PBInfo::new(trb as u8, dbquant as u8, pbplus));
466 } else {
467 pbinfo = None;
468 }
469 while br.read_bool()? { // skip PEI
470 br.read(8)?;
471 }
472 self.gob_no = 0;
473 self.mb_w = (w + 15) >> 4;
474 self.aic = aic;
475
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);
480 Ok(picinfo)
481 }
482
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);
492 self.gob_no += 1;
493 Ok(ret)
494 }
495
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() {
501 Type::I => {
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 {
506 if pi.aic {
507 let acpp = br.read_bool()?;
508 acpred = ACPredMode::DC;
509 if acpp {
510 acpred = if !br.read_bool()? { ACPredMode::Hor } else { ACPredMode::Ver };
511 }
512 }
513 }
514 let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
515 let cbp = (cbpy << 2) | (cbpc & 3);
516 let dquant = (cbpc & 4) != 0;
517 if dquant {
518 let idx = br.read(2)? as usize;
519 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
520 }
521 let mut binfo = BlockInfo::new(Type::I, cbp, q);
522 binfo.set_acpred(acpred);
523 Ok(binfo)
524 },
525 Type::P => {
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;
532 if is_intra {
533 let mut acpred = ACPredMode::None;
534 if let Some(ref pi) = info.plusinfo {
535 if pi.aic {
536 let acpp = br.read_bool()?;
537 acpred = ACPredMode::DC;
538 if acpp {
539 acpred = if !br.read_bool()? { ACPredMode::Hor } else { ACPredMode::Ver };
540 }
541 }
542 }
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);
547 if dquant {
548 let idx = br.read(2)? as usize;
549 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
550 }
551 let mut binfo = BlockInfo::new(Type::I, cbp, q);
552 binfo.set_bpart(bbinfo);
553 binfo.set_acpred(acpred);
554 if self.is_pb {
555 for _ in 0..bbinfo.get_num_mv() {
556 mvec.push(decode_mv(br, &self.tables.mv_cb)?);
557 }
558 binfo.set_b_mv(mvec.as_slice());
559 }
560 return Ok(binfo);
561 }
562
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 {
566 cbpy ^= 0xF;
567// }
568 let cbp = (cbpy << 2) | (cbpc & 3);
569 if dquant {
570 let idx = br.read(2)? as usize;
571 q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8;
572 }
573 let mut binfo = BlockInfo::new(Type::P, cbp, q);
574 binfo.set_bpart(bbinfo);
575 if !is_4x4 {
576 let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
577 binfo.set_mv(&mvec);
578 } else {
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)?
584 ];
585 binfo.set_mv(&mvec);
586 }
587 if self.is_pb {
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)?;
591 mvec.push(mv);
592 }
593 binfo.set_b_mv(mvec.as_slice());
594 }
595 Ok(binfo)
596 },
597 _ => Err(DecoderError::InvalidData),
598 }
599 }
600
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())
604 }
605
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)
609 }
610
611 fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
612}
613
614impl VivoDecoder {
615 fn new() -> Self {
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 {
629 intra_mcbpc_cb,
630 inter_mcbpc_cb,
631 cbpy_cb,
632 rl_cb,
633 aic_rl_cb,
634 mv_cb,
635 };
636
637 VivoDecoder{
638 info: NACodecInfo::new_dummy(),
2af66d55 639 dec: H263BaseDecoder::new_with_opts(H263DEC_OPT_SLICE_RESET | H263DEC_OPT_USES_GOB | H263DEC_OPT_PRED_QUANT),
31cf33ac 640 tables,
2af66d55 641 bdsp: VivoBlockDSP::new(),
31cf33ac
KS
642 lastframe: None,
643 lastpts: None,
644 width: 0,
645 height: 0,
646 }
647 }
648}
649
650impl 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();
658 self.width = w;
659 self.height = h;
660 Ok(())
661 } else {
662 Err(DecoderError::InvalidData)
663 }
664 }
665 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
666 let src = pkt.get_buffer();
667
668 if src.len() == 0 {
669 let buftype;
670 let ftype;
671 if self.lastframe.is_none() {
672 buftype = NABufferType::None;
673 ftype = FrameType::Skip;
674 } else {
675 let mut buf = None;
676 std::mem::swap(&mut self.lastframe, &mut buf);
677 buftype = buf.unwrap();
678 ftype = FrameType::B;
679 }
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);
685 self.lastpts = None;
686 }
687 return Ok(frm.into_ref());
688 }
689 let mut ibr = VivoBR::new(&src, &self.tables, self.width, self.height);
690
691 let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?;
692
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);
701 }
702 }
703 }
704
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);
709 Ok(frm.into_ref())
710 }
711 fn flush(&mut self) {
712 self.dec.flush();
713 }
714}
715
7d57ae2f
KS
716impl 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 }
720}
721
31cf33ac
KS
722
723pub fn get_decoder() -> Box<dyn NADecoder + Send> {
724 Box::new(VivoDecoder::new())
725}
726
727#[cfg(test)]
728mod test {
729 use nihav_core::codecs::RegisteredDecoders;
730 use nihav_core::demuxers::RegisteredDemuxers;
731 use nihav_codec_support::test::dec_video::*;
78fb6560 732 use crate::vivo_register_all_decoders;
31cf33ac
KS
733 use crate::vivo_register_all_demuxers;
734 #[test]
735 fn test_vivo1() {
736 let mut dmx_reg = RegisteredDemuxers::new();
737 vivo_register_all_demuxers(&mut dmx_reg);
738 let mut dec_reg = RegisteredDecoders::new();
78fb6560 739 vivo_register_all_decoders(&mut dec_reg);
31cf33ac
KS
740
741test_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));
744 }
745 #[test]
746 fn test_vivo2() {
747 let mut dmx_reg = RegisteredDemuxers::new();
748 vivo_register_all_demuxers(&mut dmx_reg);
749 let mut dec_reg = RegisteredDecoders::new();
78fb6560 750 vivo_register_all_decoders(&mut dec_reg);
31cf33ac
KS
751
752test_file_decoding("vivo", "assets/Misc/02-KimagureOrangeRoad.viv", Some(50), true, false, Some("viv2"), &dmx_reg, &dec_reg);
753panic!("end");
754// test_decoding("vivo", "vivo2", "assets/Misc/greetings.viv", Some(16),
755// &dmx_reg, &dec_reg, ExpectedTestResult::GenerateMD5Frames));
756 }
757}