Commit 6a90f9ce authored by Yushin Cho's avatar Yushin Cho Committed by Thomas Daede

Basic speed level based on minimum partition block size

Speed level decides the minimum partition block size, where recursive quadri-sect splitting stops at.
0(slowest) : BLOCK_4X4
1 : BLOCK_8X8
2 : BLOCK_16X16
3 : BLOCK_32X32
4~10(fastest) : BLOCK_64X64

Encoder option : "--speed=[0..10]" or "-s [0..10]".

Exception: SuperBlock(SB)s on right or bottom frame borders always split down to BLOCK_4X4.

In the future, min partition block size may be controlled by separate encoder option.
parent f9c95631
......@@ -124,7 +124,7 @@ use rav1e::partition::*;
use rav1e::ec;
fn write_b_bench(b: &mut Bencher) {
let mut fi = FrameInvariants::new(1024, 1024, 100);
let mut fi = FrameInvariants::new(1024, 1024, 100, 10);
let w = ec::Writer::new();
let fc = CDFContext::new();
let bc = BlockContext::new(fi.sb_width * 16, fi.sb_height * 16);
......
......@@ -14,7 +14,7 @@ fn main() {
None => None
};
let mut fi = FrameInvariants::new(width, height, files.quantizer);
let mut fi = FrameInvariants::new(width, height, files.quantizer, files.speed);
let sequence = Sequence::new();
write_ivf_header(&mut files.output_file, width, height, framerate.num, framerate.den);
......
......@@ -17,7 +17,7 @@ fn main() {
Some(rec_file) => Some(y4m::encode(width, height, framerate).write_header(rec_file).unwrap()),
None => None
};
let mut fi = FrameInvariants::new(width, height, files.quantizer);
let mut fi = FrameInvariants::new(width, height, files.quantizer, files.speed);
let sequence = Sequence::new();
write_ivf_header(&mut files.output_file, fi.padded_w, fi.padded_h, framerate.num, framerate.den);
......
......@@ -19,7 +19,7 @@ pub const MI_SIZE_LOG2: usize = 2;
const MI_SIZE: usize = (1 << MI_SIZE_LOG2);
const MAX_MIB_SIZE_LOG2: usize = (MAX_SB_SIZE_LOG2 - MI_SIZE_LOG2);
pub const MAX_MIB_SIZE: usize = (1 << MAX_MIB_SIZE_LOG2);
const MAX_MIB_MASK: usize = (MAX_MIB_SIZE - 1);
pub const MAX_MIB_MASK: usize = (MAX_MIB_SIZE - 1);
const MAX_SB_SIZE_LOG2: usize = 6;
const MAX_SB_SIZE: usize = (1 << MAX_SB_SIZE_LOG2);
......
......@@ -82,6 +82,7 @@ impl FrameState {
#[allow(dead_code)]
pub struct FrameInvariants {
pub qindex: usize,
pub speed: usize,
pub width: usize,
pub height: usize,
pub padded_w: usize,
......@@ -93,12 +94,21 @@ pub struct FrameInvariants {
pub number: u64,
pub ftype: FrameType,
pub show_existing_frame: bool,
pub min_partition_size: BlockSize,
}
impl FrameInvariants {
pub fn new(width: usize, height: usize, qindex: usize) -> FrameInvariants {
pub fn new(width: usize, height: usize, qindex: usize, speed: usize) -> FrameInvariants {
// Speed level decides the minimum partition size, i.e. higher speed --> larger min partition size,
// with exception that SBs on right or bottom frame borders split down to BLOCK_4X4.
let min_partition_size = if speed <= 0 { BlockSize::BLOCK_4X4 }
else if speed <= 1 { BlockSize::BLOCK_8X8 }
else if speed <= 2 { BlockSize::BLOCK_16X16 }
else if speed <= 3 { BlockSize::BLOCK_32X32 }
else { BlockSize::BLOCK_64X64 };
FrameInvariants {
qindex: qindex,
speed: speed,
width: width,
height: height,
padded_w: ((width+7)>>3)<<3,
......@@ -110,6 +120,7 @@ impl FrameInvariants {
number: 0,
ftype: FrameType::KEY,
show_existing_frame: false,
min_partition_size: min_partition_size,
}
}
}
......@@ -146,7 +157,8 @@ pub struct EncoderConfig {
pub output_file: Box<Write>,
pub rec_file: Option<Box<Write>>,
pub limit: u64,
pub quantizer: usize
pub quantizer: usize,
pub speed: usize
}
impl EncoderConfig {
......@@ -178,6 +190,12 @@ impl EncoderConfig {
.long("quantizer")
.takes_value(true)
.default_value("100"))
.arg(Arg::with_name("SPEED")
.help("Speed level (0(slow)-10(fast))")
.short("s")
.long("speed")
.takes_value(true)
.default_value("10"))
.get_matches();
EncoderConfig {
......@@ -193,7 +211,8 @@ impl EncoderConfig {
Box::new(File::create(&f).unwrap()) as Box<Write>
}),
limit: matches.value_of("LIMIT").unwrap().parse().unwrap(),
quantizer: matches.value_of("QP").unwrap().parse().unwrap()
quantizer: matches.value_of("QP").unwrap().parse().unwrap(),
speed: matches.value_of("SPEED").unwrap().parse().unwrap()
}
}
}
......@@ -439,11 +458,18 @@ fn encode_partition(fi: &FrameInvariants, fs: &mut FrameState, cw: &mut ContextW
return;
}
let is_sb_on_frame_border = (fi.sb_width-1) * 16 <= bo.x || (fi.sb_height-1) * 16 <= bo.y;
// TODO(anyone): Until we have RDO-based block size decision,
// split all the way down to 4x4 blocks, then do rdo_mode_decision() for each 4x4 block.
let partition = if bsize > BlockSize::BLOCK_4X4 {
PartitionType::PARTITION_SPLIT }
else { PartitionType::PARTITION_NONE };
let mut partition = PartitionType::PARTITION_NONE;
if is_sb_on_frame_border {
// SBs on right or bottom frame borders split down to BLOCK_4X4.
if bsize > BlockSize::BLOCK_4X4 { partition = PartitionType::PARTITION_SPLIT; }
} else {
if bsize > fi.min_partition_size { partition = PartitionType::PARTITION_SPLIT; }
};
assert!(mi_size_wide[bsize as usize] == mi_size_high[bsize as usize]);
......
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