Skip to content
Permalink
Browse files

Use TileRect to fix inter-prediction offsets

The inter prediction also suffered from the same confusion between
absolute offsets and offsets relative to the current tile as intra
prediction.

Pass TileRect to convert from frame offsets to tile offsets.
  • Loading branch information...
rom1v authored and tdaede committed Apr 18, 2019
1 parent 6b6c2ba commit bab3903425a1a9086613de5473bd4282c416c671
Showing with 34 additions and 16 deletions.
  1. +17 −14 src/encoder.rs
  2. +15 −0 src/me.rs
  3. +2 −2 src/partition.rs
@@ -1102,18 +1102,21 @@ pub fn motion_compensate<T: Pixel>(
) {
debug_assert!(!luma_mode.is_intra());

let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg;
let PlaneConfig { xdec: u_xdec, ydec: u_ydec, .. } = ts.input.planes[1].cfg;

// Inter mode prediction can take place once for a whole partition,
// instead of each tx-block.
let num_planes = 1 + if !luma_only && has_chroma(tile_bo, bsize, xdec, ydec) { 2 } else { 0 };
let num_planes = 1 + if !luma_only && has_chroma(tile_bo, bsize, u_xdec, u_ydec) { 2 } else { 0 };

let luma_tile_rect = ts.tile_rect();
for p in 0..num_planes {
let plane_bsize = if p == 0 { bsize }
else { get_plane_block_size(bsize, xdec, ydec) };
else { get_plane_block_size(bsize, u_xdec, u_ydec) };

let rec = &mut ts.rec.planes[p];
let po = tile_bo.plane_offset(&rec.plane_cfg);
let &PlaneConfig { xdec, ydec, .. } = rec.plane_cfg;
let tile_rect = luma_tile_rect.decimated(xdec, ydec);

let area = Area::BlockStartingAt { bo: tile_bo };
if p > 0 && bsize < BlockSize::BLOCK_8X8 {
@@ -1126,10 +1129,10 @@ pub fn motion_compensate<T: Pixel>(
some_use_intra |= cw.bc.blocks[tile_bo.with_offset(-1,-1)].mode.is_intra(); };

if some_use_intra {
luma_mode.predict_inter(fi, p, po, &mut rec.subregion_mut(area), plane_bsize.width(),
luma_mode.predict_inter(fi, tile_rect, p, po, &mut rec.subregion_mut(area), plane_bsize.width(),
plane_bsize.height(), ref_frames, mvs);
} else {
assert!(xdec == 1 && ydec == 1);
assert!(u_xdec == 1 && u_ydec == 1);
// TODO: these are absolutely only valid for 4:2:0
if bsize == BlockSize::BLOCK_4X4 {
let mv0 = cw.bc.blocks[tile_bo.with_offset(-1,-1)].mv;
@@ -1144,30 +1147,30 @@ pub fn motion_compensate<T: Pixel>(
let area2 = Area::StartingAt { x: po2.x, y: po2.y };
let po3 = PlaneOffset { x: po.x+2, y: po.y+2 };
let area3 = Area::StartingAt { x: po3.x, y: po3.y };
luma_mode.predict_inter(fi, p, po, &mut rec.subregion_mut(area), 2, 2, rf0, mv0);
luma_mode.predict_inter(fi, p, po1, &mut rec.subregion_mut(area1), 2, 2, rf1, mv1);
luma_mode.predict_inter(fi, p, po2, &mut rec.subregion_mut(area2), 2, 2, rf2, mv2);
luma_mode.predict_inter(fi, p, po3, &mut rec.subregion_mut(area3), 2, 2, ref_frames, mvs);
luma_mode.predict_inter(fi, tile_rect, p, po, &mut rec.subregion_mut(area), 2, 2, rf0, mv0);
luma_mode.predict_inter(fi, tile_rect, p, po1, &mut rec.subregion_mut(area1), 2, 2, rf1, mv1);
luma_mode.predict_inter(fi, tile_rect, p, po2, &mut rec.subregion_mut(area2), 2, 2, rf2, mv2);
luma_mode.predict_inter(fi, tile_rect, p, po3, &mut rec.subregion_mut(area3), 2, 2, ref_frames, mvs);
}
if bsize == BlockSize::BLOCK_8X4 {
let mv1 = cw.bc.blocks[tile_bo.with_offset(0,-1)].mv;
let rf1 = cw.bc.blocks[tile_bo.with_offset(0,-1)].ref_frames;
luma_mode.predict_inter(fi, p, po, &mut rec.subregion_mut(area), 4, 2, rf1, mv1);
luma_mode.predict_inter(fi, tile_rect, p, po, &mut rec.subregion_mut(area), 4, 2, rf1, mv1);
let po3 = PlaneOffset { x: po.x, y: po.y+2 };
let area3 = Area::StartingAt { x: po3.x, y: po3.y };
luma_mode.predict_inter(fi, p, po3, &mut rec.subregion_mut(area3), 4, 2, ref_frames, mvs);
luma_mode.predict_inter(fi, tile_rect, p, po3, &mut rec.subregion_mut(area3), 4, 2, ref_frames, mvs);
}
if bsize == BlockSize::BLOCK_4X8 {
let mv2 = cw.bc.blocks[tile_bo.with_offset(-1,0)].mv;
let rf2 = cw.bc.blocks[tile_bo.with_offset(-1,0)].ref_frames;
luma_mode.predict_inter(fi, p, po, &mut rec.subregion_mut(area), 2, 4, rf2, mv2);
luma_mode.predict_inter(fi, tile_rect, p, po, &mut rec.subregion_mut(area), 2, 4, rf2, mv2);
let po3 = PlaneOffset { x: po.x+2, y: po.y };
let area3 = Area::StartingAt { x: po3.x, y: po3.y };
luma_mode.predict_inter(fi, p, po3, &mut rec.subregion_mut(area3), 2, 4, ref_frames, mvs);
luma_mode.predict_inter(fi, tile_rect, p, po3, &mut rec.subregion_mut(area3), 2, 4, ref_frames, mvs);
}
}
} else {
luma_mode.predict_inter(fi, p, po, &mut rec.subregion_mut(area), plane_bsize.width(),
luma_mode.predict_inter(fi, tile_rect, p, po, &mut rec.subregion_mut(area), plane_bsize.width(),
plane_bsize.height(), ref_frames, mvs);
}
}
@@ -841,8 +841,16 @@ fn get_mv_rd_cost<T: Pixel>(
let plane_org = p_org.region(Area::StartingAt { x: po.x, y: po.y });

if let Some(ref mut tmp_plane) = tmp_plane_opt {
let tile_rect = TileRect {
x: 0,
y: 0,
width: tmp_plane.cfg.width,
height: tmp_plane.cfg.height
};

PredictionMode::NEWMV.predict_inter(
fi,
tile_rect,
0,
po,
&mut tmp_plane.as_region_mut(),
@@ -900,6 +908,12 @@ fn telescopic_subpel_search<T: Pixel>(
}

let mut tmp_plane = Plane::new(blk_w, blk_h, 0, 0, 0, 0);
let tile_rect = TileRect {
x: 0,
y: 0,
width: tmp_plane.cfg.width,
height: tmp_plane.cfg.height
};

for step in steps {
let center_mv_h = *best_mv;
@@ -925,6 +939,7 @@ fn telescopic_subpel_search<T: Pixel>(
{
mode.predict_inter(
fi,
tile_rect,
0,
po,
&mut tmp_plane.as_region_mut(),
@@ -1166,12 +1166,12 @@ impl PredictionMode {
}

pub fn predict_inter<T: Pixel>(
self, fi: &FrameInvariants<T>, p: usize, po: PlaneOffset,
self, fi: &FrameInvariants<T>, tile_rect: TileRect, p: usize, po: PlaneOffset,
dst: &mut PlaneRegionMut<'_, T>, width: usize, height: usize,
ref_frames: [RefType; 2], mvs: [MotionVector; 2]
) {
assert!(!self.is_intra());
let frame_po = dst.to_frame_plane_offset(po);
let frame_po = tile_rect.to_frame_plane_offset(po);

let mode = FilterMode::REGULAR;
let is_compound =

0 comments on commit bab3903

Please sign in to comment.
You can’t perform that action at this time.