Refactor mpeg2v for strict Clippy checks

This commit is contained in:
Dylan M. Taylor
2026-10-28 02:05:37 +00:00
parent aae601f46b
commit 0ba021388e
3 changed files with 213 additions and 138 deletions
+18 -7
View File
@@ -38,13 +38,24 @@ pub(crate) struct RefPlane<'a> {
pub h: usize,
}
/// A block to predict: integer position, half-sample flags and size.
#[derive(Clone, Copy)]
pub(crate) struct Block {
pub(crate) x: i32,
pub(crate) y: i32,
pub(crate) hx: bool,
pub(crate) hy: bool,
pub(crate) bw: usize,
pub(crate) bh: usize,
}
/// Form the `bw`×`bh` prediction at integer position (`x`, `y`) with half-sample flags into
/// `dst` (row `r` at `dst[doff + r·dstride..]`), or average it with what is there (`avg`).
/// Positions outside the reference are clamped to its edges (not allowed in conforming streams;
/// this keeps corrupt ones safe).
#[allow(clippy::too_many_arguments)]
#[inline]
pub(crate) fn predict(dst: &mut [u8], doff: usize, dstride: usize, src: RefPlane, x: i32, y: i32, hx: bool, hy: bool, bw: usize, bh: usize, avg: bool) {
pub(crate) fn predict(dst: &mut [u8], doff: usize, dstride: usize, src: RefPlane, blk: Block, avg: bool) {
let Block { x, y, hx, hy, bw, bh } = blk;
let (ex, ey) = (hx as i32, hy as i32);
let inside = x >= 0 && y >= 0 && (x + bw as i32 + ex) as usize <= src.w && (y + bh as i32 + ey) as usize <= src.h;
let mut tmp = [0u8; 16];
@@ -129,10 +140,10 @@ mod tests {
let f = frame();
let p = f.plane(0, None);
let mut d = [0u8; 4];
predict(&mut d, 0, 2, p, 1, 1, true, true, 2, 2, false);
predict(&mut d, 0, 2, p, Block { x: 1, y: 1, hx: true, hy: true, bw: 2, bh: 2 }, false);
let s = |x: usize, y: usize| f.planes[0][y * 32 + x] as u16;
assert_eq!(d[0] as u16, (s(1, 1) + s(2, 1) + s(1, 2) + s(2, 2) + 2) >> 2);
predict(&mut d, 0, 2, p, 1, 1, true, false, 2, 2, false);
predict(&mut d, 0, 2, p, Block { x: 1, y: 1, hx: true, hy: false, bw: 2, bh: 2 }, false);
assert_eq!(d[3] as u16, (s(2, 2) + s(3, 2) + 1) >> 1);
}
@@ -141,14 +152,14 @@ mod tests {
let f = frame();
let mut d = [0u8; 4];
// bottom field row 0 = frame row 1
predict(&mut d, 0, 2, f.plane(0, Some(1)), 0, 0, false, false, 2, 2, false);
predict(&mut d, 0, 2, f.plane(0, Some(1)), Block { x: 0, y: 0, hx: false, hy: false, bw: 2, bh: 2 }, false);
assert_eq!(d, [f.planes[0][32], f.planes[0][33], f.planes[0][96], f.planes[0][97]]);
// outside: clamped to the corner
predict(&mut d, 0, 2, f.plane(0, None), -10, -10, false, false, 2, 2, false);
predict(&mut d, 0, 2, f.plane(0, None), Block { x: -10, y: -10, hx: false, hy: false, bw: 2, bh: 2 }, false);
assert_eq!(d, [f.planes[0][0]; 4]);
// averaging
let mut d = [10u8; 4];
predict(&mut d, 0, 2, f.plane(0, None), -10, -10, false, false, 2, 2, true);
predict(&mut d, 0, 2, f.plane(0, None), Block { x: -10, y: -10, hx: false, hy: false, bw: 2, bh: 2 }, true);
assert_eq!(d[0], ((10 + f.planes[0][0] as u16 + 1) >> 1) as u8);
}
}
+138 -96
View File
@@ -4,7 +4,7 @@
use crate::bits::Bits;
use crate::headers::{PictureCodingExtension, PictureType, SCAN};
use crate::idct::idct;
use crate::mc::{Frame, predict};
use crate::mc::{Block, Frame, predict};
use crate::vlc::{DCT_EOB, DCT_ESCAPE, MB_BWD, MB_FWD, MB_INTRA, MB_PATTERN, MB_QUANT, MBA_ESCAPE, MBA_STUFFING, tables};
/// Non-linear quantiser_scale (Table 7-6), indexed by quantiser_scale_code.
@@ -232,7 +232,6 @@ fn skipped_mb(p: &PicParams, st: &mut SliceState, addr: usize, buf: &mut MbBuf,
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn macroblock(p: &PicParams, st: &mut SliceState, b: &mut Bits, addr: usize, buf: &mut MbBuf, blk: &mut [i32; 64], t: &mut Target) -> R<()> {
let tb = tables();
let ti = match p.ptype {
@@ -257,15 +256,81 @@ fn macroblock(p: &PicParams, st: &mut SliceState, b: &mut Bits, addr: usize, buf
if flags & MB_QUANT != 0 {
st.qscale = qscale(p, b.read(5) as usize);
}
// motion vectors
let (count, field_fmt, dual) = match (frame_pic, m.mtype) {
(true, MT_FIELD) => (2, true, false),
(true, MT_DUAL) | (false, MT_DUAL) => (1, true, true),
(true, _) => (1, false, false),
(false, MT_16X8) => (2, true, false),
(false, _) => (1, true, false),
};
let concealment = intra && p.pce.concealment_motion_vectors;
read_motion_vectors(p, st, b, &mut m, concealment)?;
if concealment {
b.skip(1); // marker_bit
}
// coded_block_pattern
let nblocks = 4 + p.chroma_blocks();
let cbp = read_cbp(p, b, flags, intra)?;
let (mbx, mby) = (addr % p.mb_width, addr / p.mb_width);
if intra {
if !concealment {
st.pmv = [[[0; 2]; 2]; 2];
}
} else {
st.dc_pred = [dc_reset(p); 3];
if p.ptype == PictureType::P && flags & MB_FWD == 0 {
// "No MC": zero vector from the same position (same-parity field in field pictures)
st.pmv = [[[0; 2]; 2]; 2];
m.flags |= MB_FWD;
m.mtype = if frame_pic { MT_FRAME } else { MT_FIELD };
m.select[0][0] = p.parity;
}
predict_mb(p, &m, mbx, mby, buf);
}
// blocks
let (cbw, cbh) = p.cmb();
for i in 0..nblocks {
if cbp & (1 << (nblocks - 1 - i)) == 0 {
continue;
}
let cc = block_component(i);
let dc_only = block(p, st, b, cc, intra, blk)?;
idct(blk, dc_only);
place_block(buf, blk, i, (cbw, cbh), dct_type, intra);
}
if p.ptype == PictureType::D {
b.skip(1); // end_of_macroblock
}
t.put(mbx, mby, buf, (cbw, cbh));
st.last = m;
Ok(())
}
/// Colour component (0 luma, 1 Cb, 2 Cr) of block `i` of a macroblock.
fn block_component(i: usize) -> usize {
if i < 4 { 0 } else { 1 + (i & 1) }
}
/// How a macroblock's motion vectors are sent.
struct MvLayout {
/// Vectors per direction: 1, or 2 for field/16x8 prediction.
count: usize,
field_fmt: bool,
dual: bool,
}
impl MvLayout {
fn of(frame_pic: bool, mtype: u8) -> MvLayout {
let (count, field_fmt, dual) = match (frame_pic, mtype) {
(true, MT_FIELD) => (2, true, false),
(true, MT_DUAL) | (false, MT_DUAL) => (1, true, true),
(true, _) => (1, false, false),
(false, MT_16X8) => (2, true, false),
(false, _) => (1, true, false),
};
MvLayout { count, field_fmt, dual }
}
}
/// Read the motion vectors (and dual-prime vectors) of a macroblock, updating the predictors.
fn read_motion_vectors(p: &PicParams, st: &mut SliceState, b: &mut Bits, m: &mut Motion, concealment: bool) -> R<()> {
let tb = tables();
let frame_pic = p.frame_picture();
let MvLayout { count, field_fmt, dual } = MvLayout::of(frame_pic, m.mtype);
let flags = m.flags;
for s in 0..2 {
let present = if s == 0 { flags & MB_FWD != 0 || concealment } else { flags & MB_BWD != 0 };
if !present {
@@ -301,75 +366,49 @@ fn macroblock(p: &PicParams, st: &mut SliceState, b: &mut Bits, addr: usize, buf
}
}
}
if concealment {
b.skip(1); // marker_bit
}
// coded_block_pattern
Ok(())
}
/// coded_block_pattern: one bit per block, first block in the most significant bit.
fn read_cbp(p: &PicParams, b: &mut Bits, flags: i16, intra: bool) -> R<u32> {
let nblocks = 4 + p.chroma_blocks();
let cbp: u32 = if flags & MB_PATTERN != 0 {
let v = tb.cbp.decode(b).ok_or(SliceError("bad coded_block_pattern"))? as u32;
Ok(if flags & MB_PATTERN != 0 {
let v = tables().cbp.decode(b).ok_or(SliceError("bad coded_block_pattern"))? as u32;
if nblocks == 8 { (v << 2) | b.read(2) } else { v }
} else if intra {
(1 << nblocks) - 1
} else {
0
};
let (mbx, mby) = (addr % p.mb_width, addr / p.mb_width);
if intra {
if !concealment {
st.pmv = [[[0; 2]; 2]; 2];
}
})
}
/// Write (intra) or add (inter) the decoded block `i` into the macroblock buffer.
fn place_block(buf: &mut MbBuf, blk: &[i32; 64], i: usize, cmb: (usize, usize), dct_type: bool, intra: bool) {
let (cbw, cbh) = cmb;
let cc = block_component(i);
let (dst, stride, x0, y0, step) = if i < 4 {
let x0 = (i & 1) * 8;
let (y0, step) = if dct_type { (i >> 1, 2) } else { ((i >> 1) * 8, 1) };
(&mut buf.y[..], 16, x0, y0, step)
} else {
st.dc_pred = [dc_reset(p); 3];
if p.ptype == PictureType::P && flags & MB_FWD == 0 {
// "No MC": zero vector from the same position (same-parity field in field pictures)
st.pmv = [[[0; 2]; 2]; 2];
m.flags |= MB_FWD;
m.mtype = if frame_pic { MT_FRAME } else { MT_FIELD };
m.select[0][0] = p.parity;
}
predict_mb(p, &m, mbx, mby, buf);
}
// blocks
let (cbw, cbh) = p.cmb();
for i in 0..nblocks {
if cbp & (1 << (nblocks - 1 - i)) == 0 {
continue;
}
let cc = if i < 4 { 0 } else { 1 + (i & 1) };
let dc_only = block(p, st, b, cc, intra, blk)?;
idct(blk, dc_only);
// placement
let (dst, stride, x0, y0, step) = if i < 4 {
let x0 = (i & 1) * 8;
let (y0, step) = if dct_type { (i >> 1, 2) } else { ((i >> 1) * 8, 1) };
(&mut buf.y[..], 16, x0, y0, step)
let k = (i - 4) >> 1; // 0 for 4:2:0; 0/1 (top/bottom) for 4:2:2
let (y0, step) = if cbh == 16 && dct_type { (k, 2) } else { (k * 8, 1) };
(&mut buf.c[cc - 1][..], cbw, 0, y0, step)
};
for r in 0..8 {
let at = (y0 + r * step) * stride + x0;
let row = &mut dst[at..at + 8];
let src = &blk[r * 8..r * 8 + 8];
if intra {
for (o, &v) in row.iter_mut().zip(src) {
*o = v.clamp(0, 255) as u8;
}
} else {
let k = (i - 4) >> 1; // 0 for 4:2:0; 0/1 (top/bottom) for 4:2:2
let (y0, step) = if cbh == 16 && dct_type { (k, 2) } else { (k * 8, 1) };
(&mut buf.c[cc - 1][..], cbw, 0, y0, step)
};
for r in 0..8 {
let at = (y0 + r * step) * stride + x0;
let row = &mut dst[at..at + 8];
let src = &blk[r * 8..r * 8 + 8];
if intra {
for (o, &v) in row.iter_mut().zip(src) {
*o = v.clamp(0, 255) as u8;
}
} else {
for (o, &v) in row.iter_mut().zip(src) {
*o = (*o as i32 + v).clamp(0, 255) as u8;
}
for (o, &v) in row.iter_mut().zip(src) {
*o = (*o as i32 + v).clamp(0, 255) as u8;
}
}
}
if p.ptype == PictureType::D {
b.skip(1); // end_of_macroblock
}
t.put(mbx, mby, buf, (cbw, cbh));
st.last = m;
Ok(())
}
/// Decode and dequantise one block into `blk` (raster order). Returns whether only the DC
@@ -504,6 +543,7 @@ fn reference<'a>(p: &PicParams<'a>, s: usize, sel: usize) -> Option<&'a Frame> {
/// Form the prediction of a non-intra macroblock in `buf` (§7.6).
fn predict_mb(p: &PicParams, m: &Motion, mbx: usize, mby: usize, buf: &mut MbBuf) {
let (cbw, cbh) = p.cmb();
let mb = Pred { mv: [0; 2], mbx, mby, cbw, cbh, avg: false };
let frame_pic = p.frame_picture();
let mut avg = false;
for s in 0..2 {
@@ -516,7 +556,7 @@ fn predict_mb(p: &PicParams, m: &Motion, mbx: usize, mby: usize, buf: &mut MbBuf
MT_FIELD => {
for r in 0..2 {
let Some(f) = reference(p, s, m.select[r][s]) else { return gray(buf) };
pred_block(p, buf, f, Some(m.select[r][s]), m.mv[r][s], mbx, mby, 8, r, 2, (cbw, cbh), avg);
pred_block(p, buf, f, Some(m.select[r][s]), Pred { mv: m.mv[r][s], avg, ..mb }, (8, r, 2));
}
}
MT_DUAL => {
@@ -525,13 +565,13 @@ fn predict_mb(p: &PicParams, m: &Motion, mbx: usize, mby: usize, buf: &mut MbBuf
let opp = 1 - par;
let (mm, e) = if par == 0 { (if p.pce.top_field_first { 1 } else { 3 }, -1) } else { (if p.pce.top_field_first { 3 } else { 1 }, 1) };
let d = dual_vector(m.mv[0][s], m.dmv, mm, e);
pred_block(p, buf, f, Some(par), m.mv[0][s], mbx, mby, 8, par, 2, (cbw, cbh), avg);
pred_block(p, buf, f, Some(opp), d, mbx, mby, 8, par, 2, (cbw, cbh), true);
pred_block(p, buf, f, Some(par), Pred { mv: m.mv[0][s], avg, ..mb }, (8, par, 2));
pred_block(p, buf, f, Some(opp), Pred { mv: d, avg: true, ..mb }, (8, par, 2));
}
}
_ => {
let Some(f) = reference(p, s, 0) else { return gray(buf) };
pred_block(p, buf, f, None, m.mv[0][s], mbx, mby, 16, 0, 1, (cbw, cbh), avg);
pred_block(p, buf, f, None, Pred { mv: m.mv[0][s], avg, ..mb }, (16, 0, 1));
}
}
} else {
@@ -539,7 +579,7 @@ fn predict_mb(p: &PicParams, m: &Motion, mbx: usize, mby: usize, buf: &mut MbBuf
MT_16X8 => {
for r in 0..2 {
let Some(f) = reference(p, s, m.select[r][s]) else { return gray(buf) };
pred_half(p, buf, f, m.select[r][s], m.mv[r][s], mbx, mby, r, (cbw, cbh), avg);
pred_half(p, buf, f, m.select[r][s], Pred { mv: m.mv[r][s], avg, ..mb }, r);
}
}
MT_DUAL => {
@@ -549,12 +589,12 @@ fn predict_mb(p: &PicParams, m: &Motion, mbx: usize, mby: usize, buf: &mut MbBuf
let Some(fo) = reference(p, s, opp) else { return gray(buf) };
let e = if same == 1 { 1 } else { -1 };
let d = dual_vector(m.mv[0][s], m.dmv, 1, e);
pred_block(p, buf, fs, Some(same), m.mv[0][s], mbx, mby, 16, 0, 1, (cbw, cbh), avg);
pred_block(p, buf, fo, Some(opp), d, mbx, mby, 16, 0, 1, (cbw, cbh), true);
pred_block(p, buf, fs, Some(same), Pred { mv: m.mv[0][s], avg, ..mb }, (16, 0, 1));
pred_block(p, buf, fo, Some(opp), Pred { mv: d, avg: true, ..mb }, (16, 0, 1));
}
_ => {
let Some(f) = reference(p, s, m.select[0][s]) else { return gray(buf) };
pred_block(p, buf, f, Some(m.select[0][s]), m.mv[0][s], mbx, mby, 16, 0, 1, (cbw, cbh), avg);
pred_block(p, buf, f, Some(m.select[0][s]), Pred { mv: m.mv[0][s], avg, ..mb }, (16, 0, 1));
}
}
}
@@ -574,47 +614,49 @@ fn dual_vector(v: [i32; 2], dmv: [i32; 2], m: i32, e: i32) -> [i32; 2] {
[scale(v[0]) + dmv[0], scale(v[1]) + e + dmv[1]]
}
/// Predict a 16-wide luma block of `lh` lines (plus chroma) from `f` (one field when `field`),
/// into `buf` lines `first + k·step`. `lh` is 16 (frame or field-picture prediction) or 8 (one
/// field of a frame macroblock).
#[allow(clippy::too_many_arguments)]
fn pred_block(
p: &PicParams,
buf: &mut MbBuf,
f: &Frame,
field: Option<usize>,
/// One motion-compensated prediction: vector, macroblock position, chroma block size, and
/// whether to average with what the buffer already holds.
#[derive(Clone, Copy)]
struct Pred {
mv: [i32; 2],
mbx: usize,
mby: usize,
lh: usize,
first: usize,
step: usize,
(cbw, cbh): (usize, usize),
cbw: usize,
cbh: usize,
avg: bool,
) {
}
/// Predict a 16-wide luma block of `lh` lines (plus chroma) from `f` (one field when `field`),
/// into `buf` lines `first + k·step`; `lines` is `(lh, first, step)`. `lh` is 16 (frame or
/// field-picture prediction) or 8 (one field of a frame macroblock).
fn pred_block(p: &PicParams, buf: &mut MbBuf, f: &Frame, field: Option<usize>, pr: Pred, lines: (usize, usize, usize)) {
let Pred { mv, mbx, mby, cbw, cbh, avg } = pr;
let (lh, first, step) = lines;
// luma: base position in the reference plane's own (frame or field) lines
let by = if lh == 8 { mby * 8 } else { mby * 16 };
let (x, y) = ((mbx * 16) as i32 + (mv[0] >> 1), by as i32 + (mv[1] >> 1));
predict(&mut buf.y, first * 16, 16 * step, f.plane(0, field), x, y, mv[0] & 1 != 0, mv[1] & 1 != 0, 16, lh, avg);
predict(&mut buf.y, first * 16, 16 * step, f.plane(0, field), Block { x, y, hx: mv[0] & 1 != 0, hy: mv[1] & 1 != 0, bw: 16, bh: lh }, avg);
let cmv = [if p.shx == 1 { mv[0] / 2 } else { mv[0] }, if p.shy == 1 { mv[1] / 2 } else { mv[1] }];
let clh = if lh == 8 { cbh / 2 } else { cbh };
let cby = mby * clh;
let (cx, cy) = ((mbx * cbw) as i32 + (cmv[0] >> 1), cby as i32 + (cmv[1] >> 1));
let cb = Block { x: cx, y: cy, hx: cmv[0] & 1 != 0, hy: cmv[1] & 1 != 0, bw: cbw, bh: clh };
for c in 0..2 {
predict(&mut buf.c[c], first * cbw, cbw * step, f.plane(1 + c, field), cx, cy, cmv[0] & 1 != 0, cmv[1] & 1 != 0, cbw, clh, avg);
predict(&mut buf.c[c], first * cbw, cbw * step, f.plane(1 + c, field), cb, avg);
}
}
/// 16x8 motion compensation in a field picture: half `r` (0 upper, 1 lower) of the macroblock.
#[allow(clippy::too_many_arguments)]
fn pred_half(p: &PicParams, buf: &mut MbBuf, f: &Frame, field: usize, mv: [i32; 2], mbx: usize, mby: usize, r: usize, (cbw, cbh): (usize, usize), avg: bool) {
fn pred_half(p: &PicParams, buf: &mut MbBuf, f: &Frame, field: usize, pr: Pred, r: usize) {
let Pred { mv, mbx, mby, cbw, cbh, avg } = pr;
let (x, y) = ((mbx * 16) as i32 + (mv[0] >> 1), (mby * 16 + r * 8) as i32 + (mv[1] >> 1));
predict(&mut buf.y, r * 8 * 16, 16, f.plane(0, Some(field)), x, y, mv[0] & 1 != 0, mv[1] & 1 != 0, 16, 8, avg);
predict(&mut buf.y, r * 8 * 16, 16, f.plane(0, Some(field)), Block { x, y, hx: mv[0] & 1 != 0, hy: mv[1] & 1 != 0, bw: 16, bh: 8 }, avg);
let cmv = [if p.shx == 1 { mv[0] / 2 } else { mv[0] }, if p.shy == 1 { mv[1] / 2 } else { mv[1] }];
let ch = cbh / 2;
let (cx, cy) = ((mbx * cbw) as i32 + (cmv[0] >> 1), (mby * cbh + r * ch) as i32 + (cmv[1] >> 1));
let cb = Block { x: cx, y: cy, hx: cmv[0] & 1 != 0, hy: cmv[1] & 1 != 0, bw: cbw, bh: ch };
for c in 0..2 {
predict(&mut buf.c[c], r * ch * cbw, cbw, f.plane(1 + c, Some(field)), cx, cy, cmv[0] & 1 != 0, cmv[1] & 1 != 0, cbw, ch, avg);
predict(&mut buf.c[c], r * ch * cbw, cbw, f.plane(1 + c, Some(field)), cb, avg);
}
}
+57 -35
View File
@@ -334,9 +334,46 @@ impl Enc {
fn macroblock(&mut self, p: &Pic, st: &mut St, mbx: usize, mby: usize) {
let frame_pic = p.structure == 3;
// macroblock_type
let (table, flags) = self.pick_mb_type(p);
let intra = flags & MB_INTRA != 0;
let concealment = intra && self.cfg.concealment;
let mut pmv = st.pmv;
let moving = flags & (MB_FWD | MB_BWD) != 0;
let mut m = self.pick_motion(p, flags, concealment, (mbx, mby), pmv);
self.w.code(code_of(table, flags));
if moving {
self.w.put(m.mtype as u32, 2);
}
let dct_type = frame_pic && !p.fpfd && (intra || flags & MB_PATTERN != 0);
if dct_type {
self.w.put(self.rng.below(2), 1);
}
if flags & MB_QUANT != 0 {
let q = self.rng.range(1, 31);
self.set_q(q);
self.w.put(q as u32, 5);
}
self.put_vectors(p, &m, concealment, &mut pmv);
// predictor resets
if intra {
if !concealment {
pmv = [[[0; 2]; 2]; 2];
}
} else {
st.dc = [self.dc_reset(); 3];
if p.ptype == PictureType::P && flags & MB_FWD == 0 {
pmv = [[[0; 2]; 2]; 2];
m.select[0][0] = p.parity;
}
}
st.pmv = pmv;
self.put_blocks(st, flags, intra);
st.last = m;
}
fn pick_mb_type(&mut self, p: &Pic) -> (&'static [(&'static str, i16)], i16) {
let quant = self.rng.chance(25);
let (table, mut flags): (&[(&str, i16)], i16) = match p.ptype {
let (table, mut flags): (&'static [(&'static str, i16)], i16) = match p.ptype {
PictureType::I => (MBTYPE_I, MB_INTRA),
PictureType::P => (
MBTYPE_P,
@@ -364,12 +401,15 @@ impl Enc {
if quant && (flags & (MB_INTRA | MB_PATTERN) != 0) {
flags |= MB_QUANT;
}
let intra = flags & MB_INTRA != 0;
let concealment = intra && self.cfg.concealment;
// motion description: pick vectors until the prediction fits
(table, flags)
}
/// Pick vectors until the prediction fits the picture and the predictors can reach them.
fn pick_motion(&mut self, p: &Pic, flags: i16, concealment: bool, pos: (usize, usize), pmv: [[[i32; 2]; 2]; 2]) -> M {
let (mbx, mby) = pos;
let frame_pic = p.structure == 3;
let mut m = M { flags, ..Default::default() };
let moving = flags & (MB_FWD | MB_BWD) != 0;
let mut pmv = st.pmv;
if moving || concealment {
let mut ok = false;
for _ in 0..40 {
@@ -431,20 +471,13 @@ impl Enc {
assert!(representable(p, &m, concealment, pmv));
}
}
self.w.code(code_of(table, flags));
if moving {
self.w.put(m.mtype as u32, 2);
}
let dct_type = frame_pic && !p.fpfd && (intra || flags & MB_PATTERN != 0);
if dct_type {
self.w.put(self.rng.below(2), 1);
}
if flags & MB_QUANT != 0 {
let q = self.rng.range(1, 31);
self.set_q(q);
self.w.put(q as u32, 5);
}
// vectors (differentially against the predictors, as the decoder forms them)
m
}
/// Vectors, coded differentially against the predictors as the decoder forms them.
fn put_vectors(&mut self, p: &Pic, m: &M, concealment: bool, pmv: &mut [[[i32; 2]; 2]; 2]) {
let frame_pic = p.structure == 3;
let flags = m.flags;
let (count, field_fmt, dualp) = match (frame_pic, m.mtype) {
(true, 1) => (2, true, false),
(_, 3) => (1, true, true),
@@ -479,20 +512,10 @@ impl Enc {
if concealment {
self.w.put(1, 1);
}
// predictor resets
if intra {
if !concealment {
pmv = [[[0; 2]; 2]; 2];
}
} else {
st.dc = [self.dc_reset(); 3];
if p.ptype == PictureType::P && flags & MB_FWD == 0 {
pmv = [[[0; 2]; 2]; 2];
m.select[0][0] = p.parity;
}
}
st.pmv = pmv;
// coded_block_pattern and blocks
}
/// coded_block_pattern and the blocks it selects.
fn put_blocks(&mut self, st: &mut St, flags: i16, intra: bool) {
let nblocks = if self.cfg.chroma == 2 { 8 } else { 6 };
let cbp: u32 = if flags & MB_PATTERN != 0 {
// the coded_block_pattern code for 0 is only for 4:2:2 and 4:4:4 (Table B.9)
@@ -513,7 +536,6 @@ impl Enc {
self.block(st, cc, intra);
}
}
st.last = m;
}
fn motion_code(&mut self, delta: i32) {