Commit b5731b2b authored by Frank Bossen's avatar Frank Bossen Committed by fbossen

Use SAD to trim the number of intra modes being evaluated in RDO

parent f9427c36
...@@ -135,9 +135,9 @@ impl SpeedSettings { ...@@ -135,9 +135,9 @@ impl SpeedSettings {
} }
fn prediction_modes_preset(speed: usize) -> PredictionModesSetting { fn prediction_modes_preset(speed: usize) -> PredictionModesSetting {
if speed <= 3 { if speed <= 1 {
PredictionModesSetting::ComplexAll PredictionModesSetting::ComplexAll
} else if speed <= 4 { } else if speed <= 3 {
PredictionModesSetting::ComplexKeyframes PredictionModesSetting::ComplexKeyframes
} else { } else {
PredictionModesSetting::Simple PredictionModesSetting::Simple
......
...@@ -1324,7 +1324,7 @@ impl BlockContext { ...@@ -1324,7 +1324,7 @@ impl BlockContext {
&self.blocks[bo.y][bo.x] &self.blocks[bo.y][bo.x]
} }
pub fn above_of(&mut self, bo: &BlockOffset) -> Block { pub fn above_of(&self, bo: &BlockOffset) -> Block {
if bo.y > 0 { if bo.y > 0 {
self.blocks[bo.y - 1][bo.x] self.blocks[bo.y - 1][bo.x]
} else { } else {
...@@ -1332,7 +1332,7 @@ impl BlockContext { ...@@ -1332,7 +1332,7 @@ impl BlockContext {
} }
} }
pub fn left_of(&mut self, bo: &BlockOffset) -> Block { pub fn left_of(&self, bo: &BlockOffset) -> Block {
if bo.x > 0 { if bo.x > 0 {
self.blocks[bo.y][bo.x - 1] self.blocks[bo.y][bo.x - 1]
} else { } else {
...@@ -1944,6 +1944,15 @@ impl ContextWriter { ...@@ -1944,6 +1944,15 @@ impl ContextWriter {
w.symbol((p == PartitionType::PARTITION_SPLIT) as u32, &cdf); w.symbol((p == PartitionType::PARTITION_SPLIT) as u32, &cdf);
} }
} }
pub fn get_cdf_intra_mode_kf(&self, bo: &BlockOffset) -> &[u16; INTRA_MODES + 1] {
static intra_mode_context: [usize; INTRA_MODES] =
[0, 1, 2, 3, 4, 4, 4, 4, 3, 0, 1, 2, 0];
let above_mode = self.bc.above_of(bo).mode as usize;
let left_mode = self.bc.left_of(bo).mode as usize;
let above_ctx = intra_mode_context[above_mode];
let left_ctx = intra_mode_context[left_mode];
&self.fc.kf_y_cdf[above_ctx][left_ctx]
}
pub fn write_intra_mode_kf( pub fn write_intra_mode_kf(
&mut self, w: &mut dyn Writer, bo: &BlockOffset, mode: PredictionMode &mut self, w: &mut dyn Writer, bo: &BlockOffset, mode: PredictionMode
) { ) {
...@@ -1956,6 +1965,9 @@ impl ContextWriter { ...@@ -1956,6 +1965,9 @@ impl ContextWriter {
let cdf = &mut self.fc.kf_y_cdf[above_ctx][left_ctx]; let cdf = &mut self.fc.kf_y_cdf[above_ctx][left_ctx];
symbol_with_update!(self, w, mode as u32, cdf); symbol_with_update!(self, w, mode as u32, cdf);
} }
pub fn get_cdf_intra_mode(&self, bsize: BlockSize) -> &[u16; INTRA_MODES + 1] {
&self.fc.y_mode_cdf[size_group_lookup[bsize as usize] as usize]
}
pub fn write_intra_mode(&mut self, w: &mut dyn Writer, bsize: BlockSize, mode: PredictionMode) { pub fn write_intra_mode(&mut self, w: &mut dyn Writer, bsize: BlockSize, mode: PredictionMode) {
let cdf = let cdf =
&mut self.fc.y_mode_cdf[size_group_lookup[bsize as usize] as usize]; &mut self.fc.y_mode_cdf[size_group_lookup[bsize as usize] as usize];
......
...@@ -769,7 +769,7 @@ where ...@@ -769,7 +769,7 @@ where
output: &mut [T], stride: usize, above: &[T], left: &[T], top_left: &[T], angle: usize, bit_depth: usize output: &mut [T], stride: usize, above: &[T], left: &[T], top_left: &[T], angle: usize, bit_depth: usize
) { ) {
let sample_max = ((1 << bit_depth) - 1) as i32; let sample_max = ((1 << bit_depth) - 1) as i32;
let angle_delta = 0; let _angle_delta = 0;
let p_angle = angle; // TODO use Mode_to_Angle let p_angle = angle; // TODO use Mode_to_Angle
......
...@@ -28,7 +28,7 @@ use me::*; ...@@ -28,7 +28,7 @@ use me::*;
use motion_compensate; use motion_compensate;
use partition::*; use partition::*;
use plane::*; use plane::*;
use predict::{RAV1E_INTRA_MODES, RAV1E_INTRA_MODES_MINIMAL, RAV1E_INTER_MODES_MINIMAL, RAV1E_INTER_COMPOUND_MODES}; use predict::{RAV1E_INTRA_MODES, RAV1E_INTER_MODES_MINIMAL, RAV1E_INTER_COMPOUND_MODES};
use quantize::dc_q; use quantize::dc_q;
use Sequence; use Sequence;
use Tune; use Tune;
...@@ -378,16 +378,6 @@ pub fn rdo_mode_decision( ...@@ -378,16 +378,6 @@ pub fn rdo_mode_decision(
let cw_checkpoint = cw.checkpoint(); let cw_checkpoint = cw.checkpoint();
// Exclude complex prediction modes at higher speed levels
let intra_mode_set = if (fi.frame_type == FrameType::KEY
&& fi.config.speed_settings.prediction_modes >= PredictionModesSetting::ComplexKeyframes)
|| (fi.frame_type == FrameType::INTER && fi.config.speed_settings.prediction_modes >= PredictionModesSetting::ComplexAll)
{
RAV1E_INTRA_MODES
} else {
RAV1E_INTRA_MODES_MINIMAL
};
let mut ref_frames_set = Vec::new(); let mut ref_frames_set = Vec::new();
let mut ref_slot_set = Vec::new(); let mut ref_slot_set = Vec::new();
let mut mvs_from_me = Vec::new(); let mut mvs_from_me = Vec::new();
...@@ -604,7 +594,49 @@ pub fn rdo_mode_decision( ...@@ -604,7 +594,49 @@ pub fn rdo_mode_decision(
}); });
if !best.skip { if !best.skip {
intra_mode_set.iter().for_each(|&luma_mode| { let tx_size = bsize.tx_size();
// Reduce number of prediction modes at higher speed levels
let num_modes_rdo = if (fi.frame_type == FrameType::KEY
&& fi.config.speed_settings.prediction_modes >= PredictionModesSetting::ComplexKeyframes)
|| (fi.frame_type == FrameType::INTER && fi.config.speed_settings.prediction_modes >= PredictionModesSetting::ComplexAll)
{
7
} else {
3
};
let intra_mode_set = RAV1E_INTRA_MODES;
let mut sads = intra_mode_set.iter().map(|&luma_mode| {
let rec = &mut fs.rec.planes[0];
let po = bo.plane_offset(&rec.cfg);
luma_mode.predict_intra(&mut rec.mut_slice(&po), tx_size, seq.bit_depth, &[0i16; 2], 0, 0, fi.w_in_b, fi.h_in_b);
let plane_org = fs.input.planes[0].slice(&po);
let plane_ref = rec.slice(&po);
(luma_mode, get_sad(&plane_org, &plane_ref, tx_size.height(), tx_size.width(), seq.bit_depth))
}).collect::<Vec<_>>();
sads.sort_by_key(|a| a.1);
// Find mode with lowest rate cost
let mut z = 32768;
let probs_all = if fi.frame_type == FrameType::INTER {
cw.get_cdf_intra_mode(bsize)
} else {
cw.get_cdf_intra_mode_kf(bo)
}.iter().take(INTRA_MODES).map(|&a| { let d = z - a; z = a; d }).collect::<Vec<_>>();
let mut probs = intra_mode_set.iter().map(|&a| (a, probs_all[a as usize])).collect::<Vec<_>>();
probs.sort_by_key(|a| !a.1);
let mut modes = Vec::new();
probs.iter().take(num_modes_rdo / 2).for_each(|&(luma_mode, _prob)| modes.push(luma_mode));
sads.iter().take(num_modes_rdo).for_each(|&(luma_mode, _sad)| if !modes.contains(&luma_mode) { modes.push(luma_mode) } );
modes.iter().take(num_modes_rdo).for_each(|&luma_mode| {
let mvs = [MotionVector { row: 0, col: 0 }; 2]; let mvs = [MotionVector { row: 0, col: 0 }; 2];
let ref_frames = [INTRA_FRAME, NONE_FRAME]; let ref_frames = [INTRA_FRAME, NONE_FRAME];
let mut mode_set_chroma = vec![luma_mode]; let mut mode_set_chroma = vec![luma_mode];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment