Skip to content

Commit

Permalink
Use TileRect to fix inter-prediction offsets
Browse files Browse the repository at this point in the history
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 20, 2019
1 parent 6b6c2ba commit bab3903
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
31 changes: 17 additions & 14 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand All @@ -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);
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/me.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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;
Expand All @@ -925,6 +939,7 @@ fn telescopic_subpel_search<T: Pixel>(
{
mode.predict_inter(
fi,
tile_rect,
0,
po,
&mut tmp_plane.as_region_mut(),
Expand Down
4 changes: 2 additions & 2 deletions src/partition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down

0 comments on commit bab3903

Please sign in to comment.