--- /dev/null
+use std::mem;
+use std::ops::Add;
+use super::*;
+use super::blockdsp;
+use super::h263code::*;
+use formats;
+
+#[derive(Debug,Clone,Copy,PartialEq)]
+pub enum Type {
+ I, P, Skip, Special
+}
+
+#[allow(dead_code)]
+#[derive(Debug,Clone,Copy)]
+pub struct PicInfo {
+ w: usize,
+ h: usize,
+ mode: Type,
+ quant: u8,
+ apm: bool,
+ umv: bool,
+ pb: bool,
+ ts: u8,
+}
+
+#[allow(dead_code)]
+impl PicInfo {
+ pub fn new(w: usize, h: usize, mode: Type, quant: u8, apm: bool, umv: bool, pb: bool, ts: u8) -> Self {
+ PicInfo{ w: w, h: h, mode: mode, quant: quant, apm: apm, umv: umv, pb: pb, ts: ts }
+ }
+ pub fn get_width(&self) -> usize { self.w }
+ pub fn get_height(&self) -> usize { self.h }
+ pub fn get_mode(&self) -> Type { self.mode }
+ pub fn get_quant(&self) -> u8 { self.quant }
+ pub fn get_apm(&self) -> bool { self.apm }
+ pub fn get_umv(&self) -> bool { self.umv }
+ pub fn is_pb(&self) -> bool { self.pb }
+ pub fn get_ts(&self) -> u8 { self.ts }
+}
+
+#[derive(Debug,Clone,Copy)]
+pub struct Slice {
+ mb_x: usize,
+ mb_y: usize,
+ quant: u8,
+}
+
+impl Slice {
+ pub fn new(mb_x: usize, mb_y: usize, quant: u8) -> Self {
+ Slice{ mb_x: mb_x, mb_y: mb_y, quant: quant }
+ }
+ pub fn get_default_slice(pinfo: &PicInfo) -> Self {
+ Slice{ mb_x: 0, mb_y: 0, quant: pinfo.get_quant() }
+ }
+ pub fn get_quant(&self) -> u8 { self.quant }
+}
+
+#[derive(Debug,Clone,Copy)]
+pub struct MV {
+ x: i16,
+ y: i16,
+}
+
+impl MV {
+ pub fn new(x: i16, y: i16) -> Self { MV{ x: x, y: y } }
+ pub fn pred(a: MV, b: MV, c: MV) -> Self {
+ let x;
+ if a.x < b.x {
+ if b.x < c.x {
+ x = b.x;
+ } else {
+ if a.x < c.x { x = c.x; } else { x = a.x; }
+ }
+ } else {
+ if b.x < c.x {
+ if a.x < c.x { x = a.x; } else { x = c.x; }
+ } else {
+ x = b.x;
+ }
+ }
+ let y;
+ if a.y < b.y {
+ if b.y < c.y {
+ y = b.y;
+ } else {
+ if a.y < c.y { y = c.y; } else { y = a.y; }
+ }
+ } else {
+ if b.y < c.y {
+ if a.y < c.y { y = a.y; } else { y = c.y; }
+ } else {
+ y = b.y;
+ }
+ }
+ MV { x: x, y: y }
+ }
+ fn add_umv(pred_mv: MV, add: MV, umv: bool) -> Self {
+ let mut new_mv = pred_mv + add;
+ if umv {
+ if pred_mv.x > 32 && new_mv.x > 63 { new_mv.x -= 64; }
+ if pred_mv.x < -31 && new_mv.x < -63 { new_mv.x += 64; }
+ if pred_mv.y > 32 && new_mv.y > 63 { new_mv.y -= 64; }
+ if pred_mv.y < -31 && new_mv.y < -63 { new_mv.y += 64; }
+ } else {
+ if new_mv.x > 31 { new_mv.x -= 64; }
+ else if new_mv.x < -32 { new_mv.x += 64; }
+ if new_mv.y > 31 { new_mv.y -= 64; }
+ else if new_mv.y < -32 { new_mv.y += 64; }
+ }
+ new_mv
+ }
+}
+
+pub const ZERO_MV: MV = MV { x: 0, y: 0 };
+
+impl Add for MV {
+ type Output = MV;
+ fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } }
+}
+
+#[derive(Debug,Clone,Copy)]
+pub struct BlockInfo {
+ intra: bool,
+ skip: bool,
+ mode: Type,
+ cbp: u8,
+ q: u8,
+ mv: [MV; 4],
+ num_mv: usize,
+ bpart: bool,
+ b_cbp: u8,
+ mv2: [MV; 4],
+ num_mv2: usize,
+}
+
+#[allow(dead_code)]
+impl BlockInfo {
+ pub fn new(mode: Type, cbp: u8, q: u8) -> Self {
+ BlockInfo {
+ intra: mode == Type::I,
+ skip: (cbp == 0) && (mode != Type::I),
+ mode: mode,
+ cbp: cbp,
+ q: q,
+ mv: [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)],
+ num_mv: 0,
+ bpart: false,
+ b_cbp: 0,
+ mv2: [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)],
+ num_mv2: 0,
+ }
+ }
+ pub fn is_intra(&self) -> bool { self.intra }
+ pub fn is_skipped(&self) -> bool { self.skip }
+ pub fn get_mode(&self) -> Type { self.mode }
+ pub fn get_cbp(&self) -> u8 { self.cbp }
+ pub fn get_q(&self) -> u8 { self.q }
+ pub fn get_num_mvs(&self) -> usize { self.num_mv }
+ pub fn get_mv(&self, idx: usize) -> MV { self.mv[idx] }
+ pub fn has_b_part(&self) -> bool { self.bpart }
+ pub fn get_cbp_b(&self) -> u8 { self.b_cbp }
+ pub fn get_num_mvs2(&self) -> usize { self.num_mv2 }
+ pub fn get_mv2(&self, idx: usize) -> MV { self.mv2[idx] }
+ pub fn set_mv(&mut self, mvs: &[MV]) {
+ if mvs.len() > 0 { self.skip = false; }
+ self.bpart = true;
+ let mut mv_arr: [MV; 4] = [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)];
+ for i in 0..mvs.len() { mv_arr[i] = mvs[i]; }
+ self.mv = mv_arr;
+ self.num_mv = mvs.len();
+ }
+ pub fn set_mv2(&mut self, cbp: u8, mvs: &[MV]) {
+ self.bpart = true;
+ self.b_cbp = cbp;
+ let mut mv_arr: [MV; 4] = [MV::new(0, 0), MV::new(0, 0), MV::new(0, 0), MV::new(0, 0)];
+ for i in 0..mvs.len() { mv_arr[i] = mvs[i]; }
+ self.mv2 = mv_arr;
+ self.num_mv2 = mvs.len();
+ }
+}
+
+pub trait BlockDecoder {
+ fn decode_pichdr(&mut self) -> DecoderResult<PicInfo>;
+ fn decode_slice_header(&mut self, pinfo: &PicInfo) -> DecoderResult<Slice>;
+ fn decode_block_header(&mut self, pinfo: &PicInfo, sinfo: &Slice) -> DecoderResult<BlockInfo>;
+ fn decode_block_intra(&mut self, info: &BlockInfo, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>;
+ fn decode_block_inter(&mut self, info: &BlockInfo, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()>;
+ fn calc_mv(&mut self, vec: MV);
+ fn is_slice_end(&mut self) -> bool;
+}
+
+#[allow(dead_code)]
+struct MVInfo {
+ mv: Vec<MV>,
+ mb_w: usize,
+ mb_stride: usize,
+ mb_start: usize,
+ top: bool,
+ umv: bool,
+}
+
+impl MVInfo {
+ fn new() -> Self { MVInfo{ mv: Vec::new(), mb_w: 0, mb_stride: 0, mb_start: 0, top: true, umv: false } }
+ fn reset(&mut self, mb_w: usize, mb_start: usize, umv: bool) {
+ self.mb_start = mb_start;
+ self.mb_w = mb_w;
+ self.mb_stride = mb_w * 2;
+ self.top = true;
+ self.mv.resize(self.mb_stride * 3, ZERO_MV);
+ self.umv = umv;
+ }
+ fn update_row(&mut self) {
+ self.mb_start = self.mb_w + 1;
+ self.top = false;
+ for i in 0..self.mb_stride {
+ self.mv[i] = self.mv[self.mb_stride * 2 + i];
+ }
+ }
+ #[allow(non_snake_case)]
+ fn predict(&mut self, mb_x: usize, blk_no: usize, use4: bool, diff: MV) -> MV {
+ let A;
+ let B;
+ let C;
+ let last = mb_x == self.mb_w - 1;
+//println!(" pred from {}.{} blk {}.{}/{} top {}", diff.x, diff.y, mb_x, blk_no,self.mb_start,self.top);
+ match blk_no {
+ 0 => {
+ if mb_x != self.mb_start {
+ A = if mb_x != 0 { self.mv[self.mb_stride + mb_x * 2 - 1] } else { ZERO_MV };
+ B = if !self.top { self.mv[ mb_x * 2] } else { A };
+ C = if !self.top && !last { self.mv[mb_x * 2 + 2] } else { ZERO_MV };
+ } else {
+ A = ZERO_MV; B = ZERO_MV; C = ZERO_MV;
+ }
+ },
+ 1 => {
+ A = self.mv[self.mb_stride + mb_x * 2];
+ B = if !self.top { self.mv[mb_x * 2 + 1] } else { A };
+ C = if !self.top && !last { self.mv[mb_x * 2 + 2] } else { A };
+ },
+ 2 => {
+ A = if mb_x != self.mb_start { self.mv[self.mb_stride * 2 + mb_x * 2 - 1] } else { ZERO_MV };
+ B = self.mv[self.mb_stride + mb_x * 2];
+ C = self.mv[self.mb_stride + mb_x * 2 + 1];
+ },
+ 3 => {
+ A = self.mv[self.mb_stride * 2 + mb_x * 2];
+ B = self.mv[self.mb_stride * 1 + mb_x * 2 + 1];
+ C = self.mv[self.mb_stride * 1 + mb_x * 2];
+ },
+ _ => { return ZERO_MV; }
+ }
+//println!(" A = {}.{} B = {}.{} C = {}.{}", A.x,A.y,B.x,B.y,C.x,C.y);
+ let pred_mv = MV::pred(A, B, C);
+ let new_mv = MV::add_umv(pred_mv, diff, self.umv);
+ if !use4 {
+ self.mv[self.mb_stride * 1 + mb_x * 2 + 0] = new_mv;
+ self.mv[self.mb_stride * 1 + mb_x * 2 + 1] = new_mv;
+ self.mv[self.mb_stride * 2 + mb_x * 2 + 0] = new_mv;
+ self.mv[self.mb_stride * 2 + mb_x * 2 + 1] = new_mv;
+ } else {
+ match blk_no {
+ 0 => { self.mv[self.mb_stride * 1 + mb_x * 2 + 0] = new_mv; },
+ 1 => { self.mv[self.mb_stride * 1 + mb_x * 2 + 1] = new_mv; },
+ 2 => { self.mv[self.mb_stride * 2 + mb_x * 2 + 0] = new_mv; },
+ 3 => { self.mv[self.mb_stride * 2 + mb_x * 2 + 1] = new_mv; },
+ _ => {},
+ };
+ }
+
+ new_mv
+ }
+ fn set_zero_mv(&mut self, mb_x: usize) {
+ self.mv[self.mb_stride * 1 + mb_x * 2 + 0] = ZERO_MV;
+ self.mv[self.mb_stride * 1 + mb_x * 2 + 1] = ZERO_MV;
+ self.mv[self.mb_stride * 2 + mb_x * 2 + 0] = ZERO_MV;
+ self.mv[self.mb_stride * 2 + mb_x * 2 + 1] = ZERO_MV;
+ }
+}
+
+fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV) {
+ let srcx = ((mv.x >> 1) as isize) + (xpos as isize);
+ let srcy = ((mv.y >> 1) as isize) + (ypos as isize);
+ let mode = ((mv.x & 1) + (mv.y & 1) * 2) as usize;
+
+ blockdsp::copy_blocks(dst, src, xpos, ypos, srcx, srcy, w, h, 0, 1, mode, H263_INTERP_FUNCS);
+}
+
+pub struct DCT8x8VideoDecoder {
+ w: usize,
+ h: usize,
+ mb_w: usize,
+ mb_h: usize,
+ num_mb: usize,
+ ftype: Type,
+ prev_frm: Option<NAVideoBuffer<u8>>,
+ cur_frm: Option<NAVideoBuffer<u8>>,
+}
+
+#[allow(dead_code)]
+impl DCT8x8VideoDecoder {
+ pub fn new() -> Self {
+ DCT8x8VideoDecoder{
+ w: 0, h: 0, mb_w: 0, mb_h: 0, num_mb: 0,
+ ftype: Type::Special,
+ prev_frm: None, cur_frm: None,
+ }
+ }
+
+ pub fn is_intra(&self) -> bool { self.ftype == Type::I }
+ pub fn get_dimensions(&self) -> (usize, usize) { (self.w, self.h) }
+
+ pub fn parse_frame(&mut self, bd: &mut BlockDecoder) -> DecoderResult<NABufferType> {
+ let pinfo = bd.decode_pichdr()?;
+ let mut mvi = MVInfo::new();
+
+//todo handle res change
+ self.w = pinfo.w;
+ self.h = pinfo.h;
+ self.mb_w = (pinfo.w + 15) >> 4;
+ self.mb_h = (pinfo.h + 15) >> 4;
+ self.num_mb = self.mb_w * self.mb_h;
+ self.ftype = pinfo.mode;
+
+ mem::swap(&mut self.cur_frm, &mut self.prev_frm);
+// if self.ftype == Type::I && !pinfo.is_pb() { self.prev_frm = None; }
+
+ let fmt = formats::YUV420_FORMAT;
+ let vinfo = NAVideoInfo::new(self.w, self.h, false, fmt);
+ let bufret = alloc_video_buffer(vinfo, 4);
+ if let Err(_) = bufret { return Err(DecoderError::InvalidData); }
+ let mut bufinfo = bufret.unwrap();
+ let mut buf = bufinfo.get_vbuf().unwrap();
+
+ let mut bbuf;
+
+ if self.prev_frm.is_some() && pinfo.is_pb() {
+ let bufret = alloc_video_buffer(vinfo, 4);
+ if let Err(_) = bufret { return Err(DecoderError::InvalidData); }
+ let mut bbufinfo = bufret.unwrap();
+ bbuf = Some(bbufinfo.get_vbuf().unwrap());
+ } else {
+ bbuf = None;
+ }
+
+ let mut slice = Slice::get_default_slice(&pinfo);
+ mvi.reset(self.mb_w, 0, pinfo.get_umv());
+
+ let mut blk: [[i16; 64]; 6] = [[0; 64]; 6];
+ for mb_y in 0..self.mb_h {
+ for mb_x in 0..self.mb_w {
+ for i in 0..6 { for j in 0..64 { blk[i][j] = 0; } }
+
+ if ((mb_x != 0) || (mb_y != 0)) && bd.is_slice_end() {
+//println!("new slice @{}.{}!",mb_x,mb_y);
+ slice = bd.decode_slice_header(&pinfo)?;
+ mvi.reset(self.mb_w, mb_x, pinfo.get_umv());
+ }
+
+ let binfo = bd.decode_block_header(&pinfo, &slice)?;
+ let cbp = binfo.get_cbp();
+//println!("mb {}.{} CBP {:X} type {:?}, {} mvs skip {}", mb_x,mb_y, cbp, binfo.get_mode(), binfo.get_num_mvs(),binfo.is_skipped());
+ if binfo.is_intra() {
+ for i in 0..6 {
+ bd.decode_block_intra(&binfo, i, (cbp & (1 << (5 - i))) != 0, &mut blk[i])?;
+ h263_idct(&mut blk[i]);
+ }
+ blockdsp::put_blocks(&mut buf, mb_x, mb_y, &blk);
+ mvi.set_zero_mv(mb_x);
+ } else if !binfo.is_skipped() {
+ if binfo.get_num_mvs() == 1 {
+ let mv = mvi.predict(mb_x, 0, false, binfo.get_mv(0));
+//println!(" 1MV {}.{}", mv.x, mv.y);
+ if let Some(ref srcbuf) = self.prev_frm {
+ copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, mv);
+ }
+ } else {
+ for blk_no in 0..4 {
+ let mv = mvi.predict(mb_x, blk_no, true, binfo.get_mv(blk_no));
+//print!(" MV {}.{}", mv.x, mv.y);
+ if let Some(ref srcbuf) = self.prev_frm {
+ copy_blocks(&mut buf, srcbuf,
+ mb_x * 16 + (blk_no & 1) * 8,
+ mb_y * 16 + (blk_no & 2) * 4, 8, 8, mv);
+ }
+ }
+//println!("");
+ }
+ for i in 0..6 {
+ bd.decode_block_inter(&binfo, i, ((cbp >> (5 - i)) & 1) != 0, &mut blk[i])?;
+ h263_idct(&mut blk[i]);
+ }
+ blockdsp::add_blocks(&mut buf, mb_x, mb_y, &blk);
+ } else {
+ mvi.set_zero_mv(mb_x);
+ if let Some(ref srcbuf) = self.prev_frm {
+ copy_blocks(&mut buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, ZERO_MV);
+ }
+ }
+ if pinfo.is_pb() && binfo.has_b_part() {
+ let mut blk: [[i16; 64]; 6] = [[0; 64]; 6];
+ let cbp = binfo.get_cbp_b();
+ for i in 0..6 {
+ bd.decode_block_inter(&binfo, i, (cbp & (1 << (5 - i))) != 0, &mut blk[i])?;
+ h263_idct(&mut blk[i]);
+ }
+ if let Some(ref mut b_buf) = bbuf {
+/* let is_fwd = false;
+ if binfo.get_num_mvs() == 1 { //todo scale
+ let mv_f = MV::add_umv(binfo.get_mv(0), binfo.get_mv2(0), pinfo.get_umv());
+ let mv_b = ZERO_MV//if component = 0 then scaled else mv_f - component
+ } else {
+ }*/
+ if let Some(ref srcbuf) = self.prev_frm {
+ copy_blocks(b_buf, srcbuf, mb_x * 16, mb_y * 16, 16, 16, ZERO_MV);
+ blockdsp::add_blocks(b_buf, mb_x, mb_y, &blk);
+ }
+ }
+ }
+
+ }
+ mvi.update_row();
+ }
+ self.cur_frm = Some(buf);
+ if pinfo.is_pb() {
+ return Ok(NABufferType::Video(bbuf.unwrap()));
+ }
+println!("unpacked all");
+ Ok(bufinfo)
+ }
+
+ pub fn get_stored_pframe(&mut self) -> DecoderResult<NABufferType> {
+ if let Some(_) = self.cur_frm {
+ let buf = self.cur_frm.clone().unwrap();
+ Ok(NABufferType::Video(buf))
+ } else {
+ Err(DecoderError::MissingReference)
+ }
+ }
+}
--- /dev/null
+use frame::*;
+
+pub fn put_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[[i16;64]; 6]) {
+ let stridey = buf.get_stride(0);
+ let strideu = buf.get_stride(1);
+ let stridev = buf.get_stride(2);
+ let mut idxy = buf.get_offset(0) + xpos * 16 + ypos * 16 * stridey;
+ let mut idxu = buf.get_offset(1) + xpos * 8 + ypos * 8 * strideu;
+ let mut idxv = buf.get_offset(2) + xpos * 8 + ypos * 8 * stridev;
+
+ let mut data = buf.get_data_mut();
+ let mut framebuf: &mut [u8] = data.as_mut_slice();
+
+ for j in 0..8 {
+ for k in 0..8 {
+ let mut v = blk[0][k + j * 8];
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k] = v as u8;
+ }
+ for k in 0..8 {
+ let mut v = blk[1][k + j * 8];
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k + 8] = v as u8;
+ }
+ idxy += stridey;
+ }
+ for j in 0..8 {
+ for k in 0..8 {
+ let mut v = blk[2][k + j * 8];
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k] = v as u8;
+ }
+ for k in 0..8 {
+ let mut v = blk[3][k + j * 8];
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k + 8] = v as u8;
+ }
+ idxy += stridey;
+ }
+
+ for j in 0..8 {
+ for k in 0..8 {
+ let mut v = blk[4][k + j * 8];
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxu + k] = v as u8;
+ }
+ for k in 0..8 {
+ let mut v = blk[5][k + j * 8];
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxv + k] = v as u8;
+ }
+ idxu += strideu;
+ idxv += stridev;
+ }
+}
+
+pub fn add_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[[i16;64]; 6]) {
+ let stridey = buf.get_stride(0);
+ let strideu = buf.get_stride(1);
+ let stridev = buf.get_stride(2);
+ let mut idxy = buf.get_offset(0) + xpos * 16 + ypos * 16 * stridey;
+ let mut idxu = buf.get_offset(1) + xpos * 8 + ypos * 8 * strideu;
+ let mut idxv = buf.get_offset(2) + xpos * 8 + ypos * 8 * stridev;
+
+ let mut data = buf.get_data_mut();
+ let mut framebuf: &mut [u8] = data.as_mut_slice();
+
+ for j in 0..8 {
+ for k in 0..8 {
+ let mut v = blk[0][k + j * 8] + (framebuf[idxy + k] as i16);
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k] = v as u8;
+ }
+ for k in 0..8 {
+ let mut v = blk[1][k + j * 8] + (framebuf[idxy + k + 8] as i16);
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k + 8] = v as u8;
+ }
+ idxy += stridey;
+ }
+ for j in 0..8 {
+ for k in 0..8 {
+ let mut v = blk[2][k + j * 8] + (framebuf[idxy + k] as i16);
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k] = v as u8;
+ }
+ for k in 0..8 {
+ let mut v = blk[3][k + j * 8] + (framebuf[idxy + k + 8] as i16);
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxy + k + 8] = v as u8;
+ }
+ idxy += stridey;
+ }
+
+ for j in 0..8 {
+ for k in 0..8 {
+ let mut v = blk[4][k + j * 8] + (framebuf[idxu + k] as i16);
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxu + k] = v as u8;
+ }
+ for k in 0..8 {
+ let mut v = blk[5][k + j * 8] + (framebuf[idxv + k] as i16);
+ if v < 0 { v = 0; } if v > 255 { v = 255; }
+ framebuf[idxv + k] = v as u8;
+ }
+ idxu += strideu;
+ idxv += stridev;
+ }
+}
+
+fn edge_emu(src: &NAVideoBuffer<u8>, xpos: isize, ypos: isize, bw: usize, bh: usize, dst: &mut [u8], dstride: usize, comp: usize) {
+ let stride = src.get_stride(comp);
+ let offs = src.get_offset(comp);
+ let (w, h) = src.get_dimensions(comp);
+ let data = src.get_data();
+ let framebuf: &[u8] = data.as_slice();
+
+ for y in 0..bh {
+ let srcy;
+ if (y as isize) + ypos < 0 { srcy = 0; }
+ else if (y as isize) + ypos >= (h as isize) { srcy = h - 1; }
+ else { srcy = ((y as isize) + ypos) as usize; }
+
+ for x in 0..bw {
+ let srcx;
+ if (x as isize) + xpos < 0 { srcx = 0; }
+ else if (x as isize) + xpos >= (w as isize) { srcx = w - 1; }
+ else { srcx = ((x as isize) + xpos) as usize; }
+ dst[x + y * dstride] = framebuf[offs + srcx + srcy * stride];
+ }
+ }
+}
+
+pub fn copy_blocks(dst: &mut NAVideoBuffer<u8>, src: &NAVideoBuffer<u8>,
+ dx: usize, dy: usize, sx: isize, sy: isize, bw: usize, bh: usize,
+ preborder: usize, postborder: usize,
+ mode: usize, interp: &[fn(&mut [u8], usize, &[u8], usize, usize, usize)])
+{
+ let pre = if mode != 0 { preborder as isize } else { 0 };
+ let post = if mode != 0 { postborder as isize } else { 0 };
+ let (w, h) = src.get_dimensions(0);
+
+ if (sx - pre < 0) || ((sx >> 1) - pre < 0) || (sx + (bw as isize) + post > (w as isize)) ||
+ (sy - pre < 0) || ((sy >> 1) - pre < 0) || (sy + (bh as isize) + post > (h as isize)) {
+ let ebuf_stride: usize = 32;
+ let mut ebuf: Vec<u8> = Vec::with_capacity(ebuf_stride * (bh + ((pre + post) as usize)));
+ ebuf.resize((((pre + post) as usize) + bh) * ebuf_stride, 0);
+
+ for comp in 0..3 {
+ let dstride = src.get_stride(comp);
+ let doff = dst.get_offset(comp);
+ let mut ddta = dst.get_data_mut();
+ let mut dbuf: &mut [u8] = ddta.as_mut_slice();
+ let x = if comp > 0 { dx/2 } else { dx };
+ let y = if comp > 0 { dy/2 } else { dy };
+ let sx_ = (if comp > 0 { sx >> 1 } else { sx }) - pre;
+ let sy_ = (if comp > 0 { sy >> 1 } else { sy }) - pre;
+ let bw_ = (if comp > 0 { bw/2 } else { bw }) + ((pre + post) as usize);
+ let bh_ = (if comp > 0 { bh/2 } else { bh }) + ((pre + post) as usize);
+ edge_emu(src, sx_ - pre, sy_ - pre, bw_, bh_,
+ ebuf.as_mut_slice(), ebuf_stride, comp);
+ let bw_ = if comp > 0 { bw/2 } else { bw };
+ let bh_ = if comp > 0 { bh/2 } else { bh };
+ (interp[mode])(&mut dbuf[doff + x + y * dstride..], dstride, ebuf.as_slice(), ebuf_stride, bw_, bh_);
+ }
+
+ } else {
+ for comp in 0..3 {
+ let sstride = src.get_stride(comp);
+ let soff = src.get_offset(comp);
+ let sdta = src.get_data();
+ let sbuf: &[u8] = sdta.as_slice();
+ let dstride = src.get_stride(comp);
+ let doff = dst.get_offset(comp);
+ let mut ddta = dst.get_data_mut();
+ let mut dbuf: &mut [u8] = ddta.as_mut_slice();
+ let x = if comp > 0 { dx/2 } else { dx };
+ let y = if comp > 0 { dy/2 } else { dy };
+ let sx_ = ((if comp > 0 { sx >> 1 } else { sx }) - pre) as usize;
+ let sy_ = ((if comp > 0 { sy >> 1 } else { sy }) - pre) as usize;
+ let bw_ = if comp > 0 { bw/2 } else { bw };
+ let bh_ = if comp > 0 { bh/2 } else { bh };
+ (interp[mode])(&mut dbuf[doff + x + y * dstride..], dstride, &sbuf[(soff + sx_ + sy_ * sstride)..], sstride, bw_, bh_);
+ }
+ }
+}
--- /dev/null
+//use super::h263data::*;
+
+/*const W1: i32 = 22725;
+const W2: i32 = 21407;
+const W3: i32 = 19266;
+const W4: i32 = 16383;
+const W5: i32 = 12873;
+const W6: i32 = 8867;
+const W7: i32 = 4520;
+
+const ROW_SHIFT: u8 = 11;
+const COL_SHIFT: u8 = 20;
+
+fn idct_row(row: &mut [i16]) {
+ let in0 = row[0] as i32;
+ let in1 = row[1] as i32;
+ let in2 = row[2] as i32;
+ let in3 = row[3] as i32;
+ let in4 = row[4] as i32;
+ let in5 = row[5] as i32;
+ let in6 = row[6] as i32;
+ let in7 = row[7] as i32;
+
+ let mut a0 = in0 * W1 + (1 << (ROW_SHIFT - 1));
+ let mut a1 = a0;
+ let mut a2 = a0;
+ let mut a3 = a0;
+
+ a0 += W2 * in2;
+ a1 += W6 * in2;
+ a2 -= W6 * in2;
+ a3 -= W2 * in2;
+
+ let mut b0 = W1 * in1 + W3 * in3;
+ let mut b1 = W3 * in1 - W7 * in3;
+ let mut b2 = W5 * in1 - W1 * in3;
+ let mut b3 = W7 * in1 - W5 * in3;
+
+ a0 += W4 * in4 + W6 * in6;
+ a1 -= W4 * in4 + W2 * in6;
+ a2 -= W4 * in4 - W2 * in6;
+ a3 += W4 * in4 - W6 * in6;
+
+ b0 += W5 * in5 + W7 * in7;
+ b1 -= W1 * in5 + W5 * in7;
+ b2 += W7 * in5 + W3 * in7;
+ b3 += W3 * in5 - W1 * in7;
+
+ row[0] = ((a0 + b0) >> ROW_SHIFT) as i16;
+ row[7] = ((a0 - b0) >> ROW_SHIFT) as i16;
+ row[1] = ((a1 + b1) >> ROW_SHIFT) as i16;
+ row[6] = ((a1 - b1) >> ROW_SHIFT) as i16;
+ row[2] = ((a2 + b2) >> ROW_SHIFT) as i16;
+ row[5] = ((a2 - b2) >> ROW_SHIFT) as i16;
+ row[3] = ((a3 + b3) >> ROW_SHIFT) as i16;
+ row[4] = ((a3 - b3) >> ROW_SHIFT) as i16;
+}
+
+fn idct_col(blk: &mut [i16; 64], off: usize) {
+ let in0 = blk[off + 0*8] as i32;
+ let in1 = blk[off + 1*8] as i32;
+ let in2 = blk[off + 2*8] as i32;
+ let in3 = blk[off + 3*8] as i32;
+ let in4 = blk[off + 4*8] as i32;
+ let in5 = blk[off + 5*8] as i32;
+ let in6 = blk[off + 6*8] as i32;
+ let in7 = blk[off + 7*8] as i32;
+
+ let mut a0 = in0 * W1 + (1 << (COL_SHIFT - 1));
+ let mut a1 = a0;
+ let mut a2 = a0;
+ let mut a3 = a0;
+
+ a0 += W2 * in2;
+ a1 += W6 * in2;
+ a2 -= W6 * in2;
+ a3 -= W2 * in2;
+
+ let mut b0 = W1 * in1 + W3 * in3;
+ let mut b1 = W3 * in1 - W7 * in3;
+ let mut b2 = W5 * in1 - W1 * in3;
+ let mut b3 = W7 * in1 - W5 * in3;
+
+ a0 += W4 * in4 + W6 * in6;
+ a1 -= W4 * in4 + W2 * in6;
+ a2 -= W4 * in4 - W2 * in6;
+ a3 += W4 * in4 - W6 * in6;
+
+ b0 += W5 * in5 + W7 * in7;
+ b1 -= W1 * in5 + W5 * in7;
+ b2 += W7 * in5 + W3 * in7;
+ b3 += W3 * in5 - W1 * in7;
+
+ blk[off + 0*8] = ((a0 + b0) >> COL_SHIFT) as i16;
+ blk[off + 7*8] = ((a0 - b0) >> COL_SHIFT) as i16;
+ blk[off + 1*8] = ((a1 + b1) >> COL_SHIFT) as i16;
+ blk[off + 6*8] = ((a1 - b1) >> COL_SHIFT) as i16;
+ blk[off + 2*8] = ((a2 + b2) >> COL_SHIFT) as i16;
+ blk[off + 5*8] = ((a2 - b2) >> COL_SHIFT) as i16;
+ blk[off + 3*8] = ((a3 + b3) >> COL_SHIFT) as i16;
+ blk[off + 4*8] = ((a3 - b3) >> COL_SHIFT) as i16;
+}
+
+#[allow(dead_code)]
+pub fn h263_idct(blk: &mut [i16; 64]) {
+ for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
+ for i in 0..8 { idct_col(blk, i); }
+}*/
+
+const W1: i32 = 2841;
+const W2: i32 = 2676;
+const W3: i32 = 2408;
+const W5: i32 = 1609;
+const W6: i32 = 1108;
+const W7: i32 = 565;
+const W8: i32 = 181;
+
+const ROW_SHIFT: u8 = 8;
+const COL_SHIFT: u8 = 14;
+
+fn idct_row(row: &mut [i16]) {
+ let in0 = ((row[0] as i32) << 11) + (1 << (ROW_SHIFT - 1));
+ let in1 = (row[4] as i32) << 11;
+ let in2 = row[6] as i32;
+ let in3 = row[2] as i32;
+ let in4 = row[1] as i32;
+ let in5 = row[7] as i32;
+ let in6 = row[5] as i32;
+ let in7 = row[3] as i32;
+
+ let tmp = W7 * (in4 + in5);
+ let a4 = tmp + (W1 - W7) * in4;
+ let a5 = tmp - (W1 + W7) * in5;
+
+ let tmp = W3 * (in6 + in7);
+ let a6 = tmp - (W3 - W5) * in6;
+ let a7 = tmp - (W3 + W5) * in7;
+
+ let tmp = in0 + in1;
+
+ let a0 = in0 - in1;
+ let t1 = W6 * (in2 + in3);
+ let a2 = t1 - (W2 + W6) * in2;
+ let a3 = t1 + (W2 - W6) * in3;
+ let b1 = a4 + a6;
+
+ let b4 = a4 - a6;
+ let t2 = a5 - a7;
+ let b6 = a5 + a7;
+ let b7 = tmp + a3;
+ let b5 = tmp - a3;
+ let b3 = a0 + a2;
+ let b0 = a0 - a2;
+ let b2 = (W8 * (b4 + t2) + 128) >> 8;
+ let b4 = (W8 * (b4 - t2) + 128) >> 8;
+
+ row[0] = ((b7 + b1) >> ROW_SHIFT) as i16;
+ row[7] = ((b7 - b1) >> ROW_SHIFT) as i16;
+ row[1] = ((b3 + b2) >> ROW_SHIFT) as i16;
+ row[6] = ((b3 - b2) >> ROW_SHIFT) as i16;
+ row[2] = ((b0 + b4) >> ROW_SHIFT) as i16;
+ row[5] = ((b0 - b4) >> ROW_SHIFT) as i16;
+ row[3] = ((b5 + b6) >> ROW_SHIFT) as i16;
+ row[4] = ((b5 - b6) >> ROW_SHIFT) as i16;
+}
+
+fn idct_col(blk: &mut [i16; 64], off: usize) {
+ let in0 = ((blk[off + 0*8] as i32) << 8) + (1 << (COL_SHIFT - 1));
+ let in1 = (blk[off + 4*8] as i32) << 8;
+ let in2 = blk[off + 6*8] as i32;
+ let in3 = blk[off + 2*8] as i32;
+ let in4 = blk[off + 1*8] as i32;
+ let in5 = blk[off + 7*8] as i32;
+ let in6 = blk[off + 5*8] as i32;
+ let in7 = blk[off + 3*8] as i32;
+
+ let tmp = W7 * (in4 + in5);
+ let a4 = (tmp + (W1 - W7) * in4) >> 3;
+ let a5 = (tmp - (W1 + W7) * in5) >> 3;
+
+ let tmp = W3 * (in6 + in7);
+ let a6 = (tmp - (W3 - W5) * in6) >> 3;
+ let a7 = (tmp - (W3 + W5) * in7) >> 3;
+
+ let tmp = in0 + in1;
+
+ let a0 = in0 - in1;
+ let t1 = W6 * (in2 + in3);
+ let a2 = (t1 - (W2 + W6) * in2) >> 3;
+ let a3 = (t1 + (W2 - W6) * in3) >> 3;
+ let b1 = a4 + a6;
+
+ let b4 = a4 - a6;
+ let t2 = a5 - a7;
+ let b6 = a5 + a7;
+ let b7 = tmp + a3;
+ let b5 = tmp - a3;
+ let b3 = a0 + a2;
+ let b0 = a0 - a2;
+ let b2 = (W8 * (b4 + t2) + 128) >> 8;
+ let b4 = (W8 * (b4 - t2) + 128) >> 8;
+
+ blk[off + 0*8] = ((b7 + b1) >> COL_SHIFT) as i16;
+ blk[off + 7*8] = ((b7 - b1) >> COL_SHIFT) as i16;
+ blk[off + 1*8] = ((b3 + b2) >> COL_SHIFT) as i16;
+ blk[off + 6*8] = ((b3 - b2) >> COL_SHIFT) as i16;
+ blk[off + 2*8] = ((b0 + b4) >> COL_SHIFT) as i16;
+ blk[off + 5*8] = ((b0 - b4) >> COL_SHIFT) as i16;
+ blk[off + 3*8] = ((b5 + b6) >> COL_SHIFT) as i16;
+ blk[off + 4*8] = ((b5 - b6) >> COL_SHIFT) as i16;
+}
+
+#[allow(dead_code)]
+pub fn h263_idct(blk: &mut [i16; 64]) {
+ for i in 0..8 { idct_row(&mut blk[i*8..(i+1)*8]); }
+ for i in 0..8 { idct_col(blk, i); }
+}
+
+fn h263_interp00(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ for x in 0..bw { dst[didx + x] = src[sidx + x]; }
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+fn h263_interp01(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ for x in 0..bw { dst[didx + x] = (((src[sidx + x] as u16) + (src[sidx + x + 1] as u16) + 1) >> 1) as u8; }
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+fn h263_interp10(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ for x in 0..bw { dst[didx + x] = (((src[sidx + x] as u16) + (src[sidx + x + sstride] as u16) + 1) >> 1) as u8; }
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+fn h263_interp11(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize)
+{
+ let mut didx = 0;
+ let mut sidx = 0;
+ for _ in 0..bh {
+ for x in 0..bw {
+ dst[didx + x] = (((src[sidx + x] as u16) +
+ (src[sidx + x + 1] as u16) +
+ (src[sidx + x + sstride] as u16) +
+ (src[sidx + x + sstride + 1] as u16) + 2) >> 2) as u8;
+ }
+ didx += dstride;
+ sidx += sstride;
+ }
+}
+
+pub const H263_INTERP_FUNCS: &[fn(&mut [u8], usize, &[u8], usize, usize, usize)] = &[
+ h263_interp00, h263_interp01, h263_interp10, h263_interp11 ];
--- /dev/null
+use io::codebook::CodebookDescReader;
+
+#[allow(dead_code)]
+pub const H263_SCALES: &[u8] = &[
+ 0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15 ];
+
+pub const H263_ZIGZAG: &[usize] = &[
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+];
+
+pub const H263_SIZES: &[(usize, usize)] = &[
+ (0, 0), (128, 96), (176, 144), (352, 288), (704, 576), (1408, 1152)
+];
+
+pub const H263_INTRA_MCBPC: &[(u8, u8)] = &[
+ (1, 1), (1, 3), (2, 3), (3, 3), (1, 4), (1, 6), (2, 6), (3, 6), (1, 9)
+];
+
+pub const H263_INTER_MCBPC: &[(u8, u8)] = &[
+ (1, 1), (3, 4), (2, 4), (5, 6), (3, 5), (4, 8), (3, 8), (3, 7),
+ (3, 3), (7, 7), (6, 7), (5, 9), (4, 6), (4, 9), (3, 9), (2, 9),
+ (2, 3), (5, 7), (4, 7), (5, 8), (1, 9), (0, 0), (0, 0), (0, 0),
+ (2, 11), (12, 13), (14, 13), (15, 13)
+];
+
+pub const H263_CBPY: &[(u8, u8)] = &[
+ ( 3, 4), ( 5, 5), ( 4, 5), ( 9, 4), ( 3, 5), ( 7, 4), ( 2, 6), (11, 4),
+ ( 2, 5), ( 3, 6), ( 5, 4), (10, 4), ( 4, 4), ( 8, 4), ( 6, 4), ( 3, 2)
+];
+
+pub const H263_MV: &[(u8, u8)] = &[
+ ( 1, 1), ( 1, 2), ( 1, 3), ( 1, 4), ( 3, 6), ( 5, 7), ( 4, 7), ( 3, 7),
+ (11, 9), (10, 9), ( 9, 9), (17, 10), (16, 10), (15, 10), (14, 10), (13, 10),
+ (12, 10), (11, 10), (10, 10), ( 9, 10), ( 8, 10), ( 7, 10), ( 6, 10), ( 5, 10),
+ ( 4, 10), ( 7, 11), ( 6, 11), ( 5, 11), ( 4, 11), ( 3, 11), ( 2, 11), ( 3, 12),
+ ( 2, 12)
+];
+
+pub const H263_DQUANT_TAB: &[i8] = &[-1, -2, 1, 2];
+
+pub struct H263ShortCodeReader { tab: &'static [(u8, u8)] }
+
+impl H263ShortCodeReader {
+ pub fn new(tab: &'static [(u8, u8)]) -> Self { H263ShortCodeReader { tab: tab } }
+}
+
+impl CodebookDescReader<u8> for H263ShortCodeReader {
+ fn bits(&mut self, idx: usize) -> u8 { let (_, bits) = self.tab[idx]; bits }
+ fn code(&mut self, idx: usize) -> u32 { let (code, _) = self.tab[idx]; code as u32 }
+ fn sym (&mut self, idx: usize) -> u8 { idx as u8 }
+ fn len(&mut self) -> usize { self.tab.len() }
+}
+
+#[derive(Clone,Copy)]
+pub struct H263RLSym { run: u8, level: i8 }
+impl H263RLSym {
+ pub fn get_run(&self) -> u8 { self.run }
+ pub fn is_last(&self) -> bool { self.level < 0 }
+ pub fn is_escape(&self) -> bool { (self.run == 0) && (self.level == 0) }
+ pub fn get_level(&self) -> i16 { if self.level < 0 { -self.level as i16 } else { self.level as i16 } }
+}
+
+pub struct H263RLCodeDesc { code: u8, bits: u8, sym: H263RLSym }
+
+macro_rules! rlcodes{
+ ($(($c:expr, $b:expr, $r:expr, $l:expr)),*) => {
+ &[$(H263RLCodeDesc{ code: $c, bits: $b, sym: H263RLSym{ run: $r, level: $l }}),*]
+ }
+}
+
+pub const H263_RL_CODES: &[H263RLCodeDesc] = rlcodes!(
+ (0x02, 2, 0, 1), (0x0F, 4, 0, 2), (0x15, 6, 0, 3), (0x17, 7, 0, 4),
+ (0x1F, 8, 0, 5), (0x25, 9, 0, 6), (0x24, 9, 0, 7), (0x21, 10, 0, 8),
+ (0x20, 10, 0, 9), (0x07, 11, 0, 10), (0x06, 11, 0, 11), (0x20, 11, 0, 12),
+ (0x06, 3, 1, 1), (0x14, 6, 1, 2), (0x1E, 8, 1, 3), (0x0F, 10, 1, 4),
+ (0x21, 11, 1, 5), (0x50, 12, 1, 6), (0x0E, 4, 2, 1), (0x1D, 8, 2, 2),
+ (0x0E, 10, 2, 3), (0x51, 12, 2, 4), (0x0D, 5, 3, 1), (0x23, 9, 3, 2),
+ (0x0D, 10, 3, 3), (0x0C, 5, 4, 1), (0x22, 9, 4, 2), (0x52, 12, 4, 3),
+ (0x0B, 5, 5, 1), (0x0C, 10, 5, 2), (0x53, 12, 5, 3), (0x13, 6, 6, 1),
+ (0x0B, 10, 6, 2), (0x54, 12, 6, 3), (0x12, 6, 7, 1), (0x0A, 10, 7, 2),
+ (0x11, 6, 8, 1), (0x09, 10, 8, 2), (0x10, 6, 9, 1), (0x08, 10, 9, 2),
+ (0x16, 7, 10, 1), (0x55, 12, 10, 2), (0x15, 7, 11, 1), (0x14, 7, 12, 1),
+ (0x1C, 8, 13, 1), (0x1B, 8, 14, 1), (0x21, 9, 15, 1), (0x20, 9, 16, 1),
+ (0x1F, 9, 17, 1), (0x1E, 9, 18, 1), (0x1D, 9, 19, 1), (0x1C, 9, 20, 1),
+ (0x1B, 9, 21, 1), (0x1A, 9, 22, 1), (0x22, 11, 23, 1), (0x23, 11, 24, 1),
+ (0x56, 12, 25, 1), (0x57, 12, 26, 1), (0x07, 4, 0, -1), (0x19, 9, 0, -2),
+ (0x05, 11, 0, -3), (0x0F, 6, 1, -1), (0x04, 11, 1, -2), (0x0E, 6, 2, -1),
+ (0x0D, 6, 3, -1), (0x0C, 6, 4, -1), (0x13, 7, 5, -1), (0x12, 7, 6, -1),
+ (0x11, 7, 7, -1), (0x10, 7, 8, -1), (0x1A, 8, 9, -1), (0x19, 8, 10, -1),
+ (0x18, 8, 11, -1), (0x17, 8, 12, -1), (0x16, 8, 13, -1), (0x15, 8, 14, -1),
+ (0x14, 8, 15, -1), (0x13, 8, 16, -1), (0x18, 9, 17, -1), (0x17, 9, 18, -1),
+ (0x16, 9, 19, -1), (0x15, 9, 20, -1), (0x14, 9, 21, -1), (0x13, 9, 22, -1),
+ (0x12, 9, 23, -1), (0x11, 9, 24, -1), (0x07, 10, 25, -1), (0x06, 10, 26, -1),
+ (0x05, 10, 27, -1), (0x04, 10, 28, -1), (0x24, 11, 29, -1), (0x25, 11, 30, -1),
+ (0x26, 11, 31, -1), (0x27, 11, 32, -1), (0x58, 12, 33, -1), (0x59, 12, 34, -1),
+ (0x5A, 12, 35, -1), (0x5B, 12, 36, -1), (0x5C, 12, 37, -1), (0x5D, 12, 38, -1),
+ (0x5E, 12, 39, -1), (0x5F, 12, 40, -1), (0x03, 7, 0, 0)
+);
+
+pub const H263_RL_CODES_AIC: &[H263RLCodeDesc] = rlcodes!(
+ (0x02, 2, 0, 1), (0x06, 3, 0, 2), (0x0E, 4, 0, 3), (0x0C, 5, 0, 4),
+ (0x0D, 5, 0, 5), (0x10, 6, 0, 6), (0x11, 6, 0, 7), (0x12, 6, 0, 8),
+ (0x16, 7, 0, 9), (0x1B, 8, 0, 10), (0x20, 9, 0, 11), (0x21, 9, 0, 12),
+ (0x1A, 9, 0, 13), (0x1B, 9, 0, 14), (0x1C, 9, 0, 15), (0x1D, 9, 0, 16),
+ (0x1E, 9, 0, 17), (0x1F, 9, 0, 18), (0x23, 11, 0, 19), (0x22, 11, 0, 20),
+ (0x57, 12, 0, 21), (0x56, 12, 0, 22), (0x55, 12, 0, 23), (0x54, 12, 0, 24),
+ (0x53, 12, 0, 25), (0x0F, 4, 1, 1), (0x14, 6, 1, 2), (0x14, 7, 1, 3),
+ (0x1E, 8, 1, 4), (0x0F, 10, 1, 5), (0x21, 11, 1, 6), (0x50, 12, 1, 7),
+ (0x0B, 5, 2, 1), (0x15, 7, 2, 2), (0x0E, 10, 2, 3), (0x09, 10, 2, 4),
+ (0x15, 6, 3, 1), (0x1D, 8, 3, 2), (0x0D, 10, 3, 3), (0x51, 12, 3, 4),
+ (0x13, 6, 4, 1), (0x23, 9, 4, 2), (0x07, 11, 4, 3), (0x17, 7, 5, 1),
+ (0x22, 9, 5, 2), (0x52, 12, 5, 3), (0x1C, 8, 6, 1), (0x0C, 10, 6, 2),
+ (0x1F, 8, 7, 1), (0x0B, 10, 7, 2), (0x25, 9, 8, 1), (0x0A, 10, 8, 2),
+ (0x24, 9, 9, 1), (0x06, 11, 9, 2), (0x21, 10, 10, 1), (0x20, 10, 11, 1),
+ (0x08, 10, 12, 1), (0x20, 11, 13, 1), (0x07, 4, 0, -1), (0x0C, 6, 0, -2),
+ (0x10, 7, 0, -3), (0x13, 8, 0, -4), (0x11, 9, 0, -5), (0x12, 9, 0, -6),
+ (0x04, 10, 0, -7), (0x27, 11, 0, -8), (0x26, 11, 0, -9), (0x5F, 12, 0,-10),
+ (0x0F, 6, 1, -1), (0x13, 9, 1, -2), (0x05, 10, 1, -3), (0x25, 11, 1, -4),
+ (0x0E, 6, 2, -1), (0x14, 9, 2, -2), (0x24, 11, 2, -3), (0x0D, 6, 3, -1),
+ (0x06, 10, 3, -2), (0x5E, 12, 3, -3), (0x11, 7, 4, -1), (0x07, 10, 4, -2),
+ (0x13, 7, 5, -1), (0x5D, 12, 5, -2), (0x12, 7, 6, -1), (0x5C, 12, 6, -2),
+ (0x14, 8, 7, -1), (0x5B, 12, 7, -2), (0x15, 8, 8, -1), (0x1A, 8, 9, -1),
+ (0x19, 8, 10, -1), (0x18, 8, 11, -1), (0x17, 8, 12, -1), (0x16, 8, 13, -1),
+ (0x19, 9, 14, -1), (0x15, 9, 15, -1), (0x16, 9, 16, -1), (0x18, 9, 17, -1),
+ (0x17, 9, 18, -1), (0x04, 11, 19, -1), (0x05, 11, 20, -1), (0x58, 12, 21, -1),
+ (0x59, 12, 22, -1), (0x5A, 12, 23, -1), (0x03, 7, 0, 0)
+);
+
+pub struct H263RLCodeReader { tab: &'static [H263RLCodeDesc] }
+
+impl H263RLCodeReader {
+ pub fn new(tab: &'static [H263RLCodeDesc]) -> Self { H263RLCodeReader { tab: tab } }
+}
+
+impl CodebookDescReader<H263RLSym> for H263RLCodeReader {
+ fn bits(&mut self, idx: usize) -> u8 { self.tab[idx].bits }
+ fn code(&mut self, idx: usize) -> u32 { self.tab[idx].code as u32 }
+ fn sym (&mut self, idx: usize) -> H263RLSym { self.tab[idx].sym }
+ fn len(&mut self) -> usize { self.tab.len() }
+}
+
--- /dev/null
+use io::bitreader::*;
+use io::codebook::*;
+use formats;
+use super::*;
+use super::blockdec::*;
+use super::h263data::*;
+
+#[allow(dead_code)]
+struct Tables {
+ intra_mcbpc_cb: Codebook<u8>,
+ inter_mcbpc_cb: Codebook<u8>,
+ cbpy_cb: Codebook<u8>,
+ rl_cb: Codebook<H263RLSym>,
+ aic_rl_cb: Codebook<H263RLSym>,
+ mv_cb: Codebook<u8>,
+}
+
+struct Intel263Decoder {
+ info: Rc<NACodecInfo>,
+ dec: DCT8x8VideoDecoder,
+ tables: Tables,
+}
+
+struct Intel263BR<'a> {
+ br: BitReader<'a>,
+ tables: &'a Tables,
+ gob_no: usize,
+ mb_w: usize,
+ is_pb: bool,
+}
+
+fn check_marker<'a>(br: &mut BitReader<'a>) -> DecoderResult<()> {
+ let mark = br.read(1)?;
+ validate!(mark == 1);
+ Ok(())
+}
+
+impl<'a> Intel263BR<'a> {
+ fn new(src: &'a [u8], tables: &'a Tables) -> Self {
+ Intel263BR {
+ br: BitReader::new(src, src.len(), BitReaderMode::BE),
+ tables: tables,
+ gob_no: 0,
+ mb_w: 0,
+ is_pb: false,
+ }
+ }
+
+ fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ let mut br = &mut self.br;
+ let mut idx = 0;
+ if intra {
+ let mut dc = br.read(8)?;
+ if dc == 255 { dc = 128; }
+ blk[0] = (dc as i16) << 3;
+ idx = 1;
+ }
+ if !coded { return Ok(()); }
+
+ let rl_cb = &self.tables.rl_cb; // could be aic too
+ let q_add = if quant == 0 { 0i16 } else { ((quant - 1) | 1) as i16 };
+ let q = (quant * 2) as i16;
+ while idx < 64 {
+ let code = br.read_cb(rl_cb)?;
+ let run;
+ let mut level;
+ let last;
+ if !code.is_escape() {
+ run = code.get_run();
+ level = code.get_level();
+ last = code.is_last();
+ if br.read_bool()? { level = -level; }
+ level = (level * q) + q_add;
+ } else {
+ last = br.read_bool()?;
+ run = br.read(6)? as u8;
+ level = br.read_s(8)? as i16;
+ if level == -128 {
+ let low = br.read(5)? as i16;
+ let top = br.read_s(6)? as i16;
+ level = (top << 5) | low;
+ }
+ level = (level * q) + q_add;
+ if level < -2048 { level = -2048; }
+ if level > 2047 { level = 2047; }
+ }
+ idx += run;
+ validate!(idx < 64);
+ let oidx = H263_ZIGZAG[idx as usize];
+ blk[oidx] = level;
+ idx += 1;
+ if last { break; }
+ }
+ Ok(())
+ }
+}
+
+fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<i16> {
+ let code = br.read_cb(mv_cb)? as i16;
+ if code == 0 { return Ok(0) }
+ if !br.read_bool()? {
+ Ok(code)
+ } else {
+ Ok(-code)
+ }
+}
+
+fn decode_mv(br: &mut BitReader, mv_cb: &Codebook<u8>) -> DecoderResult<MV> {
+ let xval = decode_mv_component(br, mv_cb)?;
+ let yval = decode_mv_component(br, mv_cb)?;
+ Ok(MV::new(xval, yval))
+}
+
+impl<'a> BlockDecoder for Intel263BR<'a> {
+
+#[allow(unused_variables)]
+ fn decode_pichdr(&mut self) -> DecoderResult<PicInfo> {
+ let mut br = &mut self.br;
+ let syncw = br.read(22)?;
+ validate!(syncw == 0x000020);
+ let tr = br.read(8)? as u8;
+ check_marker(br)?;
+ let id = br.read(1)?;
+ validate!(id == 0);
+ br.read(1)?; // split screen indicator
+ br.read(1)?; // document camera indicator
+ br.read(1)?; // freeze picture release
+ let mut sfmt = br.read(3)?;
+ validate!((sfmt != 0b000) && (sfmt != 0b110));
+ let is_intra = !br.read_bool()?;
+ let umv = br.read_bool()?;
+ br.read(1)?; // syntax arithmetic coding
+ let apm = br.read_bool()?;
+ self.is_pb = br.read_bool()?;
+ if sfmt == 0b111 {
+ sfmt = br.read(3)?;
+ validate!((sfmt != 0b000) && (sfmt != 0b111));
+ br.read(2)?; // unknown flags
+ let deblock = br.read_bool()?;
+ br.read(1)?; // unknown flag
+ let pbplus = br.read_bool()?;
+ br.read(5)?; // unknown flags
+ let marker = br.read(5)?;
+ validate!(marker == 1);
+ }
+ let w; let h;
+ if sfmt == 0b110 {
+ let par = br.read(4)?;
+ w = ((br.read(9)? + 1) * 4) as usize;
+ check_marker(br)?;
+ h = ((br.read(9)? + 1) * 4) as usize;
+ if par == 0b1111 {
+ let pixw = br.read(8)?;
+ let pixh = br.read(8)?;
+ validate!((pixw != 0) && (pixh != 0));
+ }
+ } else {
+ let (w_, h_) = H263_SIZES[sfmt as usize];
+ w = w_;
+ h = h_;
+ }
+ let quant = br.read(5)?;
+ let cpm = br.read_bool()?;
+ validate!(!cpm);
+ if self.is_pb {
+ let trb = br.read(3)?;
+ let dbquant = br.read(2)?;
+ }
+ while br.read_bool()? { // skip PEI
+ br.read(8)?;
+ }
+println!("frame {}x{} intra: {} q {} pb {} apm {} umv {} @{}", w, h, is_intra, quant, self.is_pb, apm, umv, br.tell());
+ self.gob_no = 0;
+ self.mb_w = (w + 15) >> 4;
+
+ let ftype = if is_intra { Type::I } else { Type::P };
+ let picinfo = PicInfo::new(w, h, ftype, quant as u8, apm, umv, self.is_pb, tr);
+ Ok(picinfo)
+ }
+
+ #[allow(unused_variables)]
+ fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult<Slice> {
+ let mut br = &mut self.br;
+ let gbsc = br.read(17)?;
+println!("GBSC = {}", gbsc);
+ validate!(gbsc == 1);
+ let gn = br.read(5)?;
+ let gfid = br.read(2)?;
+ let gquant = br.read(5)?;
+println!("GOB gn {:X} id {} q {}", gn, gfid, gquant);
+ let ret = Slice::new(0, self.gob_no, gquant as u8);
+ self.gob_no += 1;
+ Ok(ret)
+ }
+
+ fn decode_block_header(&mut self, info: &PicInfo, slice: &Slice) -> DecoderResult<BlockInfo> {
+ let mut br = &mut self.br;
+ let mut q = slice.get_quant();
+ match info.get_mode() {
+ Type::I => {
+ let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?;
+ while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; }
+ let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
+ let cbp = (cbpy << 2) | (cbpc & 3);
+ let dquant = (cbpc & 4) != 0;
+ if dquant {
+ let idx = br.read(2)? as usize;
+ q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
+ }
+//println!("got cbp {:X}", cbp);
+ Ok(BlockInfo::new(Type::I, cbp, q))
+ },
+ Type::P => {
+//println!("@{}",br.tell());
+ if br.read_bool()? { return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant())); }
+ let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?;
+ while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; }
+ let is_intra = (cbpc & 0x04) != 0;
+ let dquant = (cbpc & 0x08) != 0;
+ let is_4x4 = (cbpc & 0x10) != 0;
+ if is_intra {
+ let mut mvec: Vec<MV> = Vec::new();
+ let cbpb;
+ let pb_mv_count: usize;
+ if self.is_pb && br.read_bool()? {
+ let c = br.read_bool()?;
+ if c {
+ pb_mv_count = 2 - (br.read(1)? as usize);
+ cbpb = br.read(6)? as u8;
+ } else {
+ pb_mv_count = 2;
+ cbpb = 0;
+ }
+//println!(" mvc {} cbpb {:02X}", pb_mv_count, cbpb);
+ } else {
+ cbpb = 0;
+ pb_mv_count = 1;
+ }
+ let cbpy = br.read_cb(&self.tables.cbpy_cb)?;
+ let cbp = (cbpy << 2) | (cbpc & 3);
+ if dquant {
+ let idx = br.read(2)? as usize;
+ q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
+ }
+ let mut binfo = BlockInfo::new(Type::I, cbp, q);
+ if self.is_pb {
+ for _ in 0..pb_mv_count {
+ mvec.push(decode_mv(br, &self.tables.mv_cb)?);
+ }
+ binfo.set_mv2(cbpb, mvec.as_slice());
+ }
+//println!("@{}",br.tell());
+ return Ok(binfo);
+ }
+
+ let cbpb;
+ let pb_mv_count: usize;
+ if self.is_pb && br.read_bool()?{
+ let c = br.read_bool()?;
+ if c {
+ pb_mv_count = 1 - (br.read(1)? as usize);
+ cbpb = br.read(6)? as u8;
+ } else {
+ pb_mv_count = 1;
+ cbpb = 0;
+ }
+ } else {
+ cbpb = 0;
+ pb_mv_count = 0;
+ }
+ let mut cbpy = br.read_cb(&self.tables.cbpy_cb)?;
+// if /* !aiv && */(cbpc & 3) != 3 {
+ cbpy ^= 0xF;
+// }
+ let cbp = (cbpy << 2) | (cbpc & 3);
+ if dquant {
+ let idx = br.read(2)? as usize;
+ q = ((q as i16) + (H263_DQUANT_TAB[idx] as i16)) as u8;
+ }
+ let mut binfo = BlockInfo::new(Type::P, cbp, q);
+ if !is_4x4 {
+ let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?];
+//println!("@{} CBPB = {:X} mv2 {}",br.tell(), cbpb, pb_mv_count);
+ binfo.set_mv(&mvec);
+ } else {
+ let mvec: [MV; 4] = [
+ decode_mv(br, &self.tables.mv_cb)?,
+ decode_mv(br, &self.tables.mv_cb)?,
+ decode_mv(br, &self.tables.mv_cb)?,
+ decode_mv(br, &self.tables.mv_cb)?
+ ];
+ binfo.set_mv(&mvec);
+ }
+ if self.is_pb {
+ let mut mvec: Vec<MV> = Vec::with_capacity(pb_mv_count);
+ for _ in 0..pb_mv_count {
+ let mv = decode_mv(br, &self.tables.mv_cb)?;
+ mvec.push(mv);
+ }
+ binfo.set_mv2(cbpb, mvec.as_slice());
+ }
+//println!("@{}",br.tell());
+ Ok(binfo)
+ },
+ _ => { Err(DecoderError::InvalidData) },
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn decode_block_intra(&mut self, info: &BlockInfo, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ self.decode_block(info.get_q(), true, coded, blk)
+ }
+
+ #[allow(unused_variables)]
+ fn decode_block_inter(&mut self, info: &BlockInfo, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> {
+ self.decode_block(info.get_q(), false, coded, blk)
+ }
+
+#[allow(unused_variables)]
+ fn calc_mv(&mut self, vec: MV) {}
+
+ fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 }
+}
+
+impl Intel263Decoder {
+ fn new() -> Self {
+ let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC);
+ let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC);
+ let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = H263ShortCodeReader::new(H263_CBPY);
+ let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = H263RLCodeReader::new(H263_RL_CODES);
+ let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC);
+ let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let mut coderead = H263ShortCodeReader::new(H263_MV);
+ let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+ let tables = Tables {
+ intra_mcbpc_cb: intra_mcbpc_cb,
+ inter_mcbpc_cb: inter_mcbpc_cb,
+ cbpy_cb: cbpy_cb,
+ rl_cb: rl_cb,
+ aic_rl_cb: aic_rl_cb,
+ mv_cb: mv_cb,
+ };
+
+ Intel263Decoder{
+ info: Rc::new(DUMMY_CODEC_INFO),
+ dec: DCT8x8VideoDecoder::new(),
+ tables: tables,
+ }
+ }
+}
+
+impl NADecoder for Intel263Decoder {
+ fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
+ if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
+ let w = vinfo.get_width();
+ let h = vinfo.get_height();
+ let fmt = formats::YUV420_FORMAT;
+ let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
+ self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
+ Ok(())
+ } else {
+ Err(DecoderError::InvalidData)
+ }
+ }
+ fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+ let src = pkt.get_buffer();
+
+ if src.len() == 8 {
+ let bret = self.dec.get_stored_pframe();
+ let buftype;
+ let is_skip;
+ if let Ok(btype) = bret {
+ buftype = btype;
+ is_skip = false;
+ } else {
+ buftype = NABufferType::None;
+ is_skip = true;
+ }
+ let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype);
+ frm.set_keyframe(false);
+ frm.set_frame_type(if is_skip { FrameType::Skip } else { FrameType::P });
+ return Ok(Rc::new(RefCell::new(frm)));
+ }
+//println!("frame size {}", src.len());
+ let mut ibr = Intel263BR::new(&src, &self.tables);
+
+ let bufinfo = self.dec.parse_frame(&mut ibr)?;
+
+ let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
+ frm.set_keyframe(self.dec.is_intra());
+ frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P });
+ Ok(Rc::new(RefCell::new(frm)))
+ }
+}
+
+
+pub fn get_decoder() -> Box<NADecoder> {
+ Box::new(Intel263Decoder::new())
+}
+
+#[cfg(test)]
+mod test {
+ use codecs::*;
+ use demuxers::*;
+ use io::byteio::*;
+
+ #[test]
+ fn test_intel263() {
+ let avi_dmx = find_demuxer("avi").unwrap();
+ let mut file = File::open("assets/neal73_saber.avi").unwrap();
+ let mut fr = FileReader::new_read(&mut file);
+ let mut br = ByteReader::new(&mut fr);
+ let mut dmx = avi_dmx.new_demuxer(&mut br);
+ dmx.open().unwrap();
+
+ let mut decs: Vec<Option<Box<NADecoder>>> = Vec::new();
+ for i in 0..dmx.get_num_streams() {
+ let s = dmx.get_stream(i).unwrap();
+ let info = s.get_info();
+ let decfunc = find_decoder(info.get_name());
+ if let Some(df) = decfunc {
+ let mut dec = (df)();
+ dec.init(info).unwrap();
+ decs.push(Some(dec));
+ } else {
+ decs.push(None);
+ }
+ }
+
+ loop {
+ let pktres = dmx.get_frame();
+ if let Err(e) = pktres {
+ if e == DemuxerError::EOF { break; }
+ panic!("error");
+ }
+ let pkt = pktres.unwrap();
+ //if pkt.get_pts().unwrap() > 263 { break; }
+ let streamno = pkt.get_stream().get_id() as usize;
+ if let Some(ref mut dec) = decs[streamno] {
+ let frm = dec.decode(&pkt).unwrap();
+ if pkt.get_stream().get_info().is_video() {
+ write_pgmyuv("ih263_", streamno, pkt.get_pts().unwrap(), frm);
+ }
+ }
+ }
+//panic!("THE END");
+ }
+}
Bug,
}
-type DecoderResult<T> = Result<T, DecoderError>;
+pub type DecoderResult<T> = Result<T, DecoderError>;
impl From<ByteIOError> for DecoderError {
fn from(_: ByteIOError) -> Self { DecoderError::ShortData }
fn from(_: CodebookError) -> Self { DecoderError::InvalidData }
}
+macro_rules! validate {
+ ($a:expr) => { if !$a { return Err(DecoderError::InvalidData); } };
+}
+
+mod blockdsp;
+mod blockdec;
+mod h263code;
+mod h263data;
+
#[allow(dead_code)]
struct HAMShuffler {
lastframe: Option<NAVideoBuffer<u8>>,
get_decoder: fn () -> Box<NADecoder>,
}
-macro_rules! validate {
- ($a:expr) => { if !$a { return Err(DecoderError::InvalidData); } };
-}
-
#[cfg(feature="decoder_gdvvid")]
mod gremlinvideo;
#[cfg(feature="decoder_indeo2")]
mod indeo2;
#[cfg(feature="decoder_indeo3")]
mod indeo3;
+
+mod intel263;
#[cfg(feature="decoder_pcm")]
mod pcm;
#[cfg(feature="decoder_indeo3")]
DecoderInfo { name: "indeo3", get_decoder: indeo3::get_decoder },
+ DecoderInfo { name: "intel263", get_decoder: intel263::get_decoder },
+
#[cfg(feature="decoder_pcm")]
DecoderInfo { name: "pcm", get_decoder: pcm::get_decoder },
];
#[allow(dead_code)]
fn write_pgmyuv(pfx: &str, strno: usize, num: u64, frmref: NAFrameRef) {
let frm = frmref.borrow();
+ if let NABufferType::None = frm.get_buffer() { return; }
let name = format!("assets/{}out{:02}_{:04}.pgm", pfx, strno, num);
let mut ofile = File::create(name).unwrap();
let buf = frm.get_buffer().get_vbuf().unwrap();