1 use nihav_core::formats;
2 use nihav_core::codecs::*;
3 use nihav_core::io::byteio::*;
6 use super::indeo3data::*;
23 const DEFAULT_PIXEL: u8 = 0x40;
26 fn new() -> Self { Buffers { width: 0, height: 0, cw: 0, ch: 0, sbuf: Vec::new(), dbuf: Vec::new() } }
33 fn alloc(&mut self, w: usize, h: usize) {
36 self.cw = ((w >> 2) + 3) & !3;
37 self.ch = ((h >> 2) + 3) & !3;
38 self.sbuf.resize(w * h + self.cw * self.ch * 2, DEFAULT_PIXEL);
39 self.dbuf.resize(w * h + self.cw * self.ch * 2, DEFAULT_PIXEL);
41 fn flip(&mut self) { std::mem::swap(&mut self.sbuf, &mut self.dbuf); }
42 fn get_stride(&mut self, planeno: usize) -> usize {
43 if planeno == 0 { self.width } else { self.cw }
45 fn get_offset(&mut self, planeno: usize) -> usize {
47 1 => self.width * self.height,
48 2 => self.width * self.height + self.cw * self.ch,
52 fn fill_framebuf(&mut self, fbuf: &mut NAVideoBuffer<u8>) {
54 let mut soff = self.get_offset(planeno);
55 let mut doff = fbuf.get_offset(planeno);
56 let sstride = self.get_stride(planeno);
57 let dstride = fbuf.get_stride(planeno);
58 let width = if planeno == 0 { self.width } else { self.width >> 2 };
59 let height = if planeno == 0 { self.height } else { self.height >> 2 };
60 let src = self.dbuf.as_slice();
61 let dst = fbuf.get_data_mut().unwrap();
64 dst[doff + x] = src[soff + x] * 2;
71 fn copy_block(&mut self, doff: usize, soff: usize, stride: usize, w: usize, h: usize) {
75 self.dbuf[didx..][..w].copy_from_slice(&self.sbuf[sidx..][..w]);
80 fn fill_block(&mut self, doff: usize, stride: usize, w: usize, h: usize, topline: bool) {
82 let mut buf: [u8; 8] = [0; 8];
85 for i in 0..w { self.dbuf[didx + i] = DEFAULT_PIXEL; }
89 for i in 0..w { buf[i] = self.dbuf[didx - stride + i]; }
91 self.dbuf[didx..][..w].copy_from_slice(&buf[..w]);
98 #[allow(unused_variables)]
99 fn apply_delta4x4(bufs: &mut Buffers, off: usize, stride: usize,
100 deltas: &[u8], topline: bool, first_line: bool) {
101 let dst = &mut bufs.dbuf[off..][..4];
102 for i in 0..4 { dst[i] = dst[i].wrapping_add(deltas[i]) & 0x7F; }
105 #[allow(unused_variables)]
106 fn apply_delta4x8(bufs: &mut Buffers, off: usize, stride: usize,
107 deltas: &[u8], topline: bool, first_line: bool) {
108 let dst = &mut bufs.dbuf[off..][..stride + 4];
109 for i in 0..4 { dst[i + stride] = dst[i].wrapping_add(deltas[i]) & 0x7F; }
111 for i in 0..4 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
113 for i in 0..4 { dst[i] = dst[i + stride]; }
117 #[allow(unused_variables)]
118 fn apply_delta4x8m11(bufs: &mut Buffers, off: usize, stride: usize,
119 deltas: &[u8], topline: bool, first_line: bool) {
120 let dst = &mut bufs.dbuf[off..][..stride + 4];
121 for i in 0..4 { dst[i] = dst[i] .wrapping_add(deltas[i]) & 0x7F; }
122 for i in 0..4 { dst[i + stride] = dst[i + stride].wrapping_add(deltas[i]) & 0x7F; }
125 #[allow(unused_variables)]
126 fn apply_delta8x8p(bufs: &mut Buffers, off: usize, stride: usize,
127 deltas: &[u8], topline: bool, first_line: bool) {
128 let dst = &mut bufs.dbuf[off..][..stride + 8];
129 for i in 0..8 { dst[i] = dst[i] .wrapping_add(deltas[i >> 1]) & 0x7F; }
130 for i in 0..8 { dst[i + stride] = dst[i + stride].wrapping_add(deltas[i >> 1]) & 0x7F; }
133 fn apply_delta8x8i(bufs: &mut Buffers, off: usize, stride: usize,
134 deltas: &[u8], topline: bool, firstline: bool) {
135 let dst = &mut bufs.dbuf[off..][..stride + 8];
137 for i in 0..8 { dst[i + stride] = dst[i ].wrapping_add(deltas[i >> 1]) & 0x7F; }
139 for i in 0..8 { dst[i + stride] = dst[i & !1].wrapping_add(deltas[i >> 1]) & 0x7F; }
142 for i in 0..8 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
144 for i in 0..8 { dst[i] = dst[i + stride]; }
148 fn copy_line_top(bufs: &mut Buffers, off: usize, stride: usize, bw: usize, topline: bool) {
149 let mut buf: [u8; 8] = [0; 8];
151 let src = &bufs.dbuf[(off - stride)..(off - stride + bw)];
152 buf[..bw].copy_from_slice(&src[..bw]);
154 for i in 0..bw { buf[i] = DEFAULT_PIXEL; }
156 let dst = &mut bufs.dbuf[off..][..bw];
157 dst.copy_from_slice(&buf[..bw]);
160 fn copy_line_top4x4(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
161 copy_line_top(bufs, off, stride, 4, topline);
164 fn copy_line_top4x8(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
165 copy_line_top(bufs, off, stride, 4, topline);
166 copy_line_top(bufs, off + stride, stride, 4, false);
169 fn copy_line_top8x8(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
170 let mut buf: [u8; 8] = [0; 8];
172 let src = &bufs.dbuf[(off - stride)..(off - stride + 8)];
173 for i in 0..8 { buf[i] = src[i & !1]; }
175 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
177 let dst = &mut bufs.dbuf[off..][..8];
178 dst.copy_from_slice(&buf[..8]);
181 fn fill_block8x8(bufs: &mut Buffers, doff: usize, stride: usize, h: usize, topline: bool, firstline: bool) {
183 let mut buf: [u8; 8] = [0; 8];
185 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
187 for i in 0..8 { buf[i] = bufs.dbuf[doff - stride + i]; }
189 if topline && !firstline {
190 for i in 0..4 { buf[i * 2 + 1] = buf[i * 2]; }
191 for i in 0..8 { bufs.dbuf[doff + i] = (bufs.dbuf[doff - stride + i] + buf[i]) >> 1; }
194 let start = if !topline { 0 } else { 1 };
199 bufs.dbuf[didx..][..8].copy_from_slice(&buf[..8]);
204 struct Indeo3Decoder {
205 info: NACodecInfoRef,
214 requant_tab: [[u8; 128]; 8],
217 #[derive(Clone,Copy)]
229 fn new(w: u16, h: u16) -> Self {
230 IV3Cell { x: 0, y: 0, w, h, d: 20, vqt: false, mv: None }
232 fn split_h(&self) -> (Self, Self) {
233 let h1 = if self.h > 2 { ((self.h + 2) >> 2) << 1 } else { 1 };
234 let h2 = self.h - h1;
235 let mut cell1 = *self;
238 let mut cell2 = *self;
244 fn split_w(&self, stripw: u16) -> (Self, Self) {
245 let w1 = if self.w > stripw {
246 if self.w > stripw * 2 { stripw * 2 } else { stripw }
248 if self.w > 2 { ((self.w + 2) >> 2) << 1 } else { 1 }
250 let w2 = self.w - w1;
251 let mut cell1 = *self;
254 let mut cell2 = *self;
260 fn no_mv(&self) -> bool { self.mv.is_none() }
263 struct CellDecParams {
269 apply_delta: fn (&mut Buffers, usize, usize, &[u8], bool, bool),
270 copy_line_top: fn (&mut Buffers, usize, usize, bool),
273 const FRMH_TAG: u32 = ((b'F' as u32) << 24) | ((b'R' as u32) << 16)
274 | ((b'M' as u32) << 8) | (b'H' as u32);
276 const H_SPLIT: u8 = 0;
277 const V_SPLIT: u8 = 1;
278 const SKIP_OR_TREE: u8 = 2;
282 const REQUANT_OFF: [i32; 8] = [ 0, 1, 0, 4, 4, 1, 0, 1 ];
284 let dummy_info = NACodecInfo::new_dummy();
286 let mut requant_tab = [[0u8; 128]; 8];
288 let step = (i as i32) + 2;
289 let start = if (i == 3) || (i == 4) { -3 } else { step / 2 };
292 requant_tab[i][j] = (((j as i32) + start) / step * step + REQUANT_OFF[i]) as u8;
293 if requant_tab[i][j] < 128 {
294 last = requant_tab[i][j];
296 requant_tab[i][j] = last;
300 requant_tab[1][7] = 10;
301 requant_tab[1][119] = 118;
302 requant_tab[1][120] = 118;
303 requant_tab[4][8] = 10;
305 Indeo3Decoder { info: dummy_info, bpos: 0, bbuf: 0, width: 0, height: 0,
306 mvs: Vec::new(), altquant: [0; 16],
307 vq_offset: 0, bufs: Buffers::new(), requant_tab }
310 fn br_reset(&mut self) {
315 fn get_2bits(&mut self, br: &mut ByteReader) -> DecoderResult<u8> {
317 self.bbuf = br.read_byte()?;
321 Ok((self.bbuf >> self.bpos) & 0x3)
324 #[allow(clippy::cognitive_complexity)]
325 fn decode_cell_data(&mut self, br: &mut ByteReader, cell: IV3Cell,
326 off: usize, stride: usize, params: CellDecParams, vq_idx: u8) -> DecoderResult<()> {
327 let blk_w = cell.w * 4 / params.bw;
328 let blk_h = cell.h * 4 / params.bh;
329 let scale: usize = if params.bh == 4 { 1 } else { 2 };
331 validate!((((cell.w * 4) % params.bw) == 0) && (((cell.h * 4) % params.bh) == 0));
333 let mut run_blocks = 0;
334 let mut run_skip = false;
336 let mut didx: usize = ((cell.x*4) as usize) + ((cell.y * 4) as usize) * stride + off;
342 let mv = cell.mv.unwrap();
343 let mx = i16::from(mv.x);
344 let my = i16::from(mv.y);
345 let l = (cell.x as i16) * 4 + mx;
346 let t = (cell.y as i16) * 4 + my;
347 let r = ((cell.x + cell.w) as i16) * 4 + mx;
348 let b = ((cell.y + cell.h) as i16) * 4 + my;
351 validate!(r <= (self.width as i16));
352 validate!(b <= (self.height as i16));
353 sidx = (l as usize) + (t as usize) * stride + off;
356 let requant_tab = &self.requant_tab[(vq_idx & 7) as usize];
359 for x in 0..(cell.w as usize) * 4 {
360 self.bufs.dbuf[didx + x - stride] = requant_tab[self.bufs.dbuf[didx + x - stride] as usize];
364 for x in 0..(cell.w as usize) * 4 {
365 self.bufs.sbuf[sidx + x] = requant_tab[self.bufs.sbuf[sidx + x] as usize];
370 let mut xoff: usize = 0;
373 if !run_skip || !cell.no_mv() {
374 if !(params.bw == 8 && cell.no_mv()) {
376 self.bufs.copy_block(didx + xoff, sidx + xoff, stride,
377 params.bw as usize, params.bh as usize);
379 self.bufs.fill_block(didx + xoff, stride,
380 params.bw as usize, params.bh as usize,
381 (cell.y == 0) && (y == 0));
384 fill_block8x8(&mut self.bufs,
385 didx + xoff, stride, 8,
386 y == 0, (cell.y == 0) && (y == 0));
391 let mut line: usize = 0;
393 let c = br.read_byte()?;
395 let delta_tab = if params.hq {
396 IVI3_DELTA_CBS[params.tab[line & 1]]
398 IVI3_DELTA_CBS[params.tab[1]]
402 if (c as usize) < delta_tab.data.len()/2 {
403 idx1 = br.read_byte()? as usize;
404 validate!(idx1 < delta_tab.data.len() / 2);
407 let tmp = (c as usize) - delta_tab.data.len()/2;
408 idx1 = tmp / (delta_tab.quad_radix as usize);
409 idx2 = tmp % (delta_tab.quad_radix as usize);
410 if params.swap_q[line & 1] {
411 mem::swap(&mut idx1, &mut idx2);
414 let deltas: [u8; 4] = [delta_tab.data[idx1 * 2] as u8,
415 delta_tab.data[idx1 * 2 + 1] as u8,
416 delta_tab.data[idx2 * 2 + 0] as u8,
417 delta_tab.data[idx2 * 2 + 1] as u8];
418 let topline = (cell.y == 0) && (y == 0) && (line == 0);
419 let first_line = (y == 0) && (line == 0);
421 (params.copy_line_top)(&mut self.bufs,
422 didx + xoff + line * scale * stride,
425 self.bufs.copy_block(didx + xoff + line * scale * stride,
426 sidx + xoff + line * scale * stride,
427 stride, params.bw as usize, scale);
429 (params.apply_delta)(&mut self.bufs,
430 didx + xoff + line * scale * stride,
431 stride, &deltas, topline, first_line);
434 let mut tocopy: usize = 0;
435 let mut do_copy = true;
436 if c == 0xF8 { return Err(DecoderError::InvalidData); }
440 validate!(line == 0);
442 do_copy = !cell.no_mv();
445 validate!(line == 0);
447 do_copy = !cell.no_mv();
450 let c = br.read_byte()?;
451 validate!((c < 64) && ((c & 0x1F) != 0));
452 run_blocks = (c & 0x1F) - 1;
453 run_skip = (c & 0x20) != 0;
455 if params.bw == 4 && cell.no_mv() && run_skip {
465 let nl = 257 - i16::from(c) - (line as i16);
467 tocopy = nl as usize;
470 if !(params.bh == 8 && cell.no_mv()) {
472 self.bufs.copy_block(didx + xoff + line * scale * stride,
473 sidx + xoff + line * scale * stride,
474 stride, params.bw as usize,
477 self.bufs.fill_block(didx + xoff + line * scale * stride,
478 stride, params.bw as usize,
480 (cell.y == 0) && (y == 0) && (line == 0));
483 fill_block8x8(&mut self.bufs,
484 didx + xoff + line * 2 * stride,
486 (y == 0) && (line == 0),
487 (cell.y == 0) && (y == 0) && (line == 0));
494 xoff += params.bw as usize;
496 didx += stride * (params.bh as usize);
497 sidx += stride * (params.bh as usize);
502 fn copy_cell(&mut self, cell: IV3Cell, off: usize, stride: usize) -> DecoderResult<()> {
503 if cell.no_mv() { return Err(DecoderError::InvalidData); }
504 let mv = cell.mv.unwrap();
505 let mx = i16::from(mv.x);
506 let my = i16::from(mv.y);
507 let l = (cell.x as i16) * 4 + mx;
508 let t = (cell.y as i16) * 4 + my;
509 let r = ((cell.x + cell.w) as i16) * 4 + mx;
510 let b = ((cell.y + cell.h) as i16) * 4 + my;
513 validate!(r <= (self.width as i16));
514 validate!(b <= (self.height as i16));
515 let sidx: usize = off + (l as usize) + (t as usize) * stride;
516 let didx: usize = off + ((cell.x * 4) as usize) + ((cell.y * 4) as usize) * stride;
517 self.bufs.copy_block(didx, sidx, stride, (cell.w * 4) as usize, (cell.h * 4) as usize);
521 fn decode_cell(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
522 stride: usize, intra: bool) -> DecoderResult<()> {
523 let code = br.read_byte()?;
524 let mode = code >> 4;
525 let vq_idx = code & 0xF;
527 let mut idx1: usize = vq_idx as usize;
528 let mut idx2: usize = vq_idx as usize;
529 if (mode == 1) || (mode == 4) {
530 let c = self.altquant[vq_idx as usize];
531 idx1 = (c >> 4) as usize;
532 idx2 = (c & 0xF) as usize;
534 idx1 += self.vq_offset as usize;
535 idx2 += self.vq_offset as usize;
537 validate!((idx1 < 24) && (idx2 < 24));
539 let mut cp = CellDecParams {
542 swap_q: [idx2 >= 16, idx1 >= 16],
544 apply_delta: apply_delta4x4,
545 copy_line_top: copy_line_top4x4,
547 if (mode == 0) || (mode == 1) {
551 } else if (mode == 3) || (mode == 4) {
552 if !cell.no_mv() { return Err(DecoderError::InvalidData); }
556 cp.apply_delta = apply_delta4x8;
557 cp.copy_line_top = copy_line_top4x8;
558 } else if mode == 10 {
561 cp.apply_delta = apply_delta8x8p;
563 cp.apply_delta = apply_delta8x8i;
567 cp.copy_line_top = copy_line_top8x8;
568 } else if mode == 11 {
569 if cell.no_mv() { return Err(DecoderError::InvalidData); }
573 cp.apply_delta = apply_delta4x8m11;
574 cp.copy_line_top = copy_line_top4x8;
576 return Err(DecoderError::InvalidData);
578 self.decode_cell_data(br, cell, off, stride, cp, vq_idx)
581 fn parse_tree(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
582 stride: usize, stripw: u16, intra: bool) -> DecoderResult<()> {
583 let op = self.get_2bits(br)?;
585 validate!(cell.h > 1);
586 validate!(cell.d > 0);
587 let (cell1, cell2) = cell.split_h();
588 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
589 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
591 } else if op == V_SPLIT {
592 validate!(cell.w > 1);
593 validate!(cell.d > 0);
594 let (cell1, cell2) = cell.split_w(stripw);
595 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
596 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
598 } else if op == SKIP_OR_TREE {
600 let mut newcell = cell;
603 self.parse_tree(br, newcell, off, stride, stripw, intra)
606 let code = self.get_2bits(br)?;
608 if code == 1 { return Err(DecoderError::NotImplemented); }
609 self.copy_cell(cell, off, stride)
613 let mut newcell = cell;
616 let mv_idx = br.read_byte()? as usize;
617 validate!(mv_idx < self.mvs.len());
618 newcell.mv = Some(self.mvs[mv_idx]);
619 self.parse_tree(br, newcell, off, stride, stripw, intra)
621 self.decode_cell(br, cell, off, stride, intra)
626 fn decode_plane_intra(&mut self, br: &mut ByteReader, planeno: usize,
627 start: u64, end: u64) -> DecoderResult<()> {
628 let offs = self.bufs.get_offset(planeno);
629 let stride = self.bufs.get_stride(planeno);
630 br.seek(SeekFrom::Start(start))?;
632 let nvec = br.read_u32le()?;
633 validate!(nvec == 0); // for intra there should be no mc_vecs
636 let x = br.read_byte()? as i8;
637 let y = br.read_byte()? as i8;
638 self.mvs.push(MV{ x, y });
641 let (cellwidth, cellheight) = if planeno == 0 {
642 (self.bufs.width >> 2, self.bufs.height >> 2)
644 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
646 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
648 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, true)?;
649 validate!(br.tell() <= end);
653 fn decode_plane_inter(&mut self, br: &mut ByteReader, planeno: usize,
654 start: u64, end: u64) -> DecoderResult<()> {
655 let offs = self.bufs.get_offset(planeno);
656 let stride = self.bufs.get_stride(planeno);
657 br.seek(SeekFrom::Start(start))?;
659 let nvec = br.read_u32le()?;
660 validate!(nvec <= 256); // for intra there should be no mc_vecs
663 let y = br.read_byte()? as i8;
664 let x = br.read_byte()? as i8;
665 self.mvs.push(MV{ x, y });
668 let (cellwidth, cellheight) = if planeno == 0 {
669 (self.bufs.width >> 2, self.bufs.height >> 2)
671 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
673 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
675 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, false)?;
676 validate!(br.tell() <= end);
681 const FLAG_KEYFRAME: u16 = 1 << 2;
682 const FLAG_NONREF: u16 = 1 << 8;
684 impl NADecoder for Indeo3Decoder {
685 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
686 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
687 let w = vinfo.get_width();
688 let h = vinfo.get_height();
689 let fmt = formats::YUV410_FORMAT;
690 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
691 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
695 Err(DecoderError::InvalidData)
698 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
699 let src = pkt.get_buffer();
700 let mut mr = MemoryReader::new_read(&src);
701 let mut br = ByteReader::new(&mut mr);
702 let frameno = br.read_u32le()?;
703 let hdr_2 = br.read_u32le()?;
704 let check = br.read_u32le()?;
705 let size = br.read_u32le()?;
707 let data_start = br.tell();
709 if (frameno ^ hdr_2 ^ size ^ FRMH_TAG) != check {
710 return Err(DecoderError::InvalidData);
712 if i64::from(size) > br.left() { return Err(DecoderError::InvalidData); }
713 let ver = br.read_u16le()?;
714 if ver != 32 { return Err(DecoderError::NotImplemented); }
715 let flags = br.read_u16le()?;
716 let size2 = br.read_u32le()?;
718 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
719 frm.set_keyframe(false);
720 frm.set_frame_type(FrameType::Skip);
721 return Ok(frm.into_ref());
723 validate!(((size2 + 7) >> 3) <= size);
724 let cb = br.read_byte()?;
727 let height = br.read_u16le()?;
728 let width = br.read_u16le()?;
729 validate!((width >= 16) && (width <= 640));
730 validate!((height >= 16) && (height <= 640));
731 validate!(((width & 3) == 0) && ((height & 3) == 0));
733 if (self.bufs.width != (width as usize)) || (self.bufs.height != (height as usize)) {
734 self.bufs.alloc(width as usize, height as usize);
735 vinfo = NAVideoInfo::new(width as usize, height as usize, false, formats::YUV410_FORMAT);
737 vinfo = self.info.get_properties().get_video_info().unwrap();
740 self.height = height;
742 let yoff = br.read_u32le()?;
743 let uoff = br.read_u32le()?;
744 let voff = br.read_u32le()?;
745 if yoff > size { return Err(DecoderError::InvalidData); }
746 if uoff > size { return Err(DecoderError::InvalidData); }
747 if voff > size { return Err(DecoderError::InvalidData); }
750 br.read_buf(&mut self.altquant)?;
752 let mut yend = src.len() as u32;//size;
753 if (uoff < yend) && (uoff > yoff) { yend = uoff; }
754 if (voff < yend) && (voff > yoff) { yend = voff; }
756 if (yoff < uend) && (yoff > uoff) { uend = yoff; }
757 if (voff < uend) && (voff > uoff) { uend = voff; }
759 if (yoff < vend) && (yoff > voff) { vend = yoff; }
760 if (uoff < vend) && (uoff > voff) { vend = uoff; }
762 let intraframe = (flags & FLAG_KEYFRAME) != 0;
763 let bufinfo = alloc_video_buffer(vinfo, 4)?;
764 let mut buf = bufinfo.get_vbuf().unwrap();
765 let ystart = data_start + u64::from(yoff);
766 let ustart = data_start + u64::from(uoff);
767 let vstart = data_start + u64::from(voff);
768 let yendpos = data_start + u64::from(yend);
769 let uendpos = data_start + u64::from(uend);
770 let vendpos = data_start + u64::from(vend);
772 self.decode_plane_intra(&mut br, 0, ystart, yendpos)?;
773 self.decode_plane_intra(&mut br, 1, vstart, vendpos)?;
774 self.decode_plane_intra(&mut br, 2, ustart, uendpos)?;
776 self.decode_plane_inter(&mut br, 0, ystart, yendpos)?;
777 self.decode_plane_inter(&mut br, 1, vstart, vendpos)?;
778 self.decode_plane_inter(&mut br, 2, ustart, uendpos)?;
780 self.bufs.fill_framebuf(&mut buf);
781 if (flags & FLAG_NONREF) == 0 { self.bufs.flip(); }
782 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
783 frm.set_keyframe(intraframe);
784 frm.set_frame_type(if intraframe { FrameType::I } else { FrameType::P });
787 fn flush(&mut self) {
792 impl NAOptionHandler for Indeo3Decoder {
793 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
794 fn set_options(&mut self, _options: &[NAOption]) { }
795 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
798 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
799 Box::new(Indeo3Decoder::new())
804 use nihav_core::codecs::RegisteredDecoders;
805 use nihav_core::demuxers::RegisteredDemuxers;
806 use nihav_codec_support::test::dec_video::*;
807 use crate::indeo_register_all_decoders;
808 use nihav_commonfmt::generic_register_all_demuxers;
811 let mut dmx_reg = RegisteredDemuxers::new();
812 generic_register_all_demuxers(&mut dmx_reg);
813 let mut dec_reg = RegisteredDecoders::new();
814 indeo_register_all_decoders(&mut dec_reg);
816 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/iv32_example.avi
817 test_decoding("avi", "indeo3", "assets/Indeo/iv32_example.avi", Some(10),
818 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
819 [0x90be698e, 0x326db071, 0x08e8c6a5, 0x39349acc],
820 [0x25d677fc, 0x63f96aaa, 0xd412ca98, 0x61416313],
821 [0xc4368250, 0x63e7b6bc, 0xffcff950, 0x11f13239],
822 [0x7e869758, 0x027abc2e, 0x25204bca, 0x93fbaa03],
823 [0x5a1e822c, 0x2b1a4cd5, 0x72059843, 0xe5689ad1],
824 [0x3a971cce, 0x5ec22135, 0x1a45f802, 0x0f5f9264],
825 [0x0a65f782, 0xd8767cf3, 0x878b4b8d, 0xfc94c88b],
826 [0x4ac70139, 0x3300eac1, 0xba84b068, 0x47f5ff29],
827 [0x3e8c8ec4, 0x9421b38c, 0x580abbbd, 0x92792d19],
828 [0x9096ee9b, 0x8dd9fb14, 0x981e31e3, 0x3ffd7d29],
829 [0x22dc71ec, 0x3d8f6f7e, 0x1a198982, 0x41d17ecc]]));