Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add developer CLI flags for tuning encoder internals #3047

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/rav1e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ on:

jobs:
rustfmt-clippy:

runs-on: ubuntu-22.04

steps:
Expand Down Expand Up @@ -193,7 +192,7 @@ jobs:
- name: Check extra features
if: matrix.toolchain == 'stable' && matrix.conf == 'check-extra-feats'
run: |
cargo check --features=check_asm,capi,dump_lookahead_data,serialize,bench --all-targets
cargo check --features=check_asm,capi,dump_lookahead_data,serialize,bench,devel --all-targets
- name: Check extra features
if: matrix.toolchain == 'stable' && matrix.conf == 'check-unstable-feats'
run: |
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ default-run = "rav1e"

[features]
unstable = []
# Exposes extra flags for tuning compiler internals.
# Intended to be used by developers to find ideal internal settings.
devel = []
channel-api = ["crossbeam"]
decode_test = ["aom-sys"]
decode_test_dav1d = ["dav1d-sys"]
Expand Down
45 changes: 45 additions & 0 deletions src/api/config/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,50 @@ pub struct EncoderConfig {

/// Settings which affect the encoding speed vs. quality trade-off.
pub speed_settings: SpeedSettings,

/// Advanced settings which are intended for use by developers.
/// Non-developers should use the default values.
pub advanced_flags: AdvancedTuning,
}

/// Advanced settings that are intended for use by developers
/// for tuning compiler internals.
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct AdvancedTuning {
/// Controls the strength of the deblock filter, as a multiplier to the default.
pub deblock_strength: f32,
/// Controls the sharpness of the deblock filter. Accepts a value from 0-7.
pub deblock_sharpness: u8,
/// Controls the ratio between intra frame and inter frame quantizers, as a multiplier.
/// Default is 1.0. Higher values create a higher quantizer difference, while lower values
/// create a lower quantizer difference. A value of 0.0 would mean that I and P quantizers
/// are the same.
pub ip_ratio: f32,
/// Controls the ratio between "P"-frame and "B"-frame quantizers, as a multiplier.
/// Default is 1.0. Higher values create a higher quantizer difference, while lower values
/// create a lower quantizer difference. A value of 0.0 would mean that P and B quantizers
/// are the same.
pub pb_ratio: f32,
/// Controls the ratio between frame quantizers in the levels of the pyramid betweem "B"-frames,
/// as a multiplier. Default is 1.0. Higher values create a higher quantizer difference,
/// while lower values create a lower quantizer difference. A value of 0.0 would mean that
/// B0 and B1 quantizers are the same.
pub b_ratio: f32,
/// Controls the strength of temporal RDO, as a multiplier to the default.
pub temporal_rdo_strength: f32,
}

impl Default for AdvancedTuning {
fn default() -> Self {
Self {
deblock_strength: 1.0,
deblock_sharpness: 0,
ip_ratio: 1.0,
pb_ratio: 1.0,
b_ratio: 1.0,
temporal_rdo_strength: 1.0,
}
}
}

/// Default preset for `EncoderConfig`: it is a balance between quality and
Expand Down Expand Up @@ -171,6 +215,7 @@ impl EncoderConfig {
tile_rows: 0,
tiles: 0,
speed_settings: SpeedSettings::from_preset(speed),
advanced_flags: Default::default(),
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/api/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2165,6 +2165,7 @@ fn log_q_exp_overflow() {
},
..Default::default()
},
advanced_flags: Default::default(),
};
let config = Config::new().with_encoder_config(enc).with_threads(1);

Expand Down Expand Up @@ -2242,6 +2243,7 @@ fn guess_frame_subtypes_assert() {
},
..Default::default()
},
advanced_flags: Default::default(),
};
let config = Config::new().with_encoder_config(enc).with_threads(1);

Expand Down
62 changes: 61 additions & 1 deletion src/bin/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,53 @@ pub struct CliOptions {
#[clap(long, short, value_parser, help_heading = "DEBUGGING")]
pub reconstruction: Option<PathBuf>,

/// Controls the strength of the deblock filter, as a multiplier to the default.
#[cfg(feature = "devel")]
#[clap(long, value_parser = positive_float, default_value_t=1.0f32, help_heading = "ADVANCED")]
pub deblock_strength: f32,
/// Controls the sharpness of the deblock filter. Accepts a value from 0-7.
#[cfg(feature = "devel")]
#[clap(long, value_parser = clap::value_parser!(u8).range(0..=7), default_value_t=0, help_heading = "ADVANCED")]
pub deblock_sharpness: u8,
/// Controls the ratio between intra frame and inter frame quantizers, as a multiplier.
/// Higher values create a higher quantizer difference, while lower values
/// create a lower quantizer difference. A value of 0.0 would mean that I and P quantizers
/// are the same.
#[cfg(feature = "devel")]
#[clap(long, value_parser = positive_float, default_value_t=1.0f32, help_heading = "ADVANCED")]
pub ip_ratio: f32,
/// Controls the ratio between "P"-frame and "B"-frame quantizers, as a multiplier.
/// Default is 1.0. Higher values create a higher quantizer difference, while lower values
/// create a lower quantizer difference. A value of 0.0 would mean that P and B quantizers
/// are the same.
#[cfg(feature = "devel")]
#[clap(long, value_parser = positive_float, default_value_t=1.0f32, help_heading = "ADVANCED")]
pub pb_ratio: f32,
/// Controls the ratio between frame quantizers in the levels of the pyramid betweem "B"-frames,
/// as a multiplier. Default is 1.0. Higher values create a higher quantizer difference,
/// while lower values create a lower quantizer difference. A value of 0.0 would mean that
/// B0 and B1 quantizers are the same.
#[cfg(feature = "devel")]
#[clap(long, value_parser = positive_float, default_value_t=1.0f32, help_heading = "ADVANCED")]
pub b_ratio: f32,
/// Controls the strength of temporal RDO, as a multiplier to the default.
#[cfg(feature = "devel")]
#[clap(long, value_parser = positive_float, default_value_t=1.0f32, help_heading = "ADVANCED")]
pub temporal_rdo_strength: f32,

#[clap(subcommand)]
pub command: Option<Commands>,
}

#[cfg(feature = "devel")]
fn positive_float(input: &str) -> Result<f32, String> {
let value = input.parse::<f32>().map_err(|e| e.to_string())?;
if value < 0.0 {
return Err("Value must not be negative".to_string());
}
Ok(value)
}

fn get_version() -> &'static str {
static VERSION_STR: Lazy<String> = Lazy::new(|| {
format!(
Expand Down Expand Up @@ -299,7 +342,7 @@ pub enum Commands {
#[clap(long, short, value_parser)]
save_config: Option<PathBuf>,
/// Load the encoder configuration from a toml file
#[clap(long, short, value_parser, conflicts_with = "save-config")]
#[clap(long, short, value_parser, conflicts_with = "save_config")]
load_config: Option<PathBuf>,
},
}
Expand Down Expand Up @@ -484,6 +527,18 @@ pub fn parse_cli() -> Result<ParsedCliOptions, CliError> {
})
}

#[cfg(feature = "devel")]
const fn parse_advanced_flags(cli: &CliOptions) -> AdvancedTuning {
AdvancedTuning {
deblock_strength: cli.deblock_strength,
deblock_sharpness: cli.deblock_sharpness,
ip_ratio: cli.ip_ratio,
pb_ratio: cli.pb_ratio,
b_ratio: cli.b_ratio,
temporal_rdo_strength: cli.temporal_rdo_strength,
}
}

fn parse_config(matches: &CliOptions) -> Result<EncoderConfig, CliError> {
let maybe_quantizer = matches.quantizer;
let maybe_bitrate = matches.bitrate;
Expand Down Expand Up @@ -689,5 +744,10 @@ fn parse_config(matches: &CliOptions) -> Result<EncoderConfig, CliError> {
cfg.speed_settings.scene_detection_mode = SceneDetectionSpeed::None;
}

#[cfg(feature = "devel")]
{
cfg.advanced_flags = parse_advanced_flags(matches);
}

Ok(cfg)
}
20 changes: 18 additions & 2 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ impl<T: Pixel> FrameState<T> {
cdfs: CDFContext::new(0),
context_update_tile_id: 0,
max_tile_size_bytes: 0,
deblock: Default::default(),
deblock: DeblockState::new(&fi.config, fi.frame_type),
segmentation: Default::default(),
restoration: rs,
frame_me_stats: me_stats,
Expand Down Expand Up @@ -497,7 +497,7 @@ impl<T: Pixel> FrameState<T> {
cdfs: CDFContext::new(0),
context_update_tile_id: 0,
max_tile_size_bytes: 0,
deblock: Default::default(),
deblock: DeblockState::new(&fi.config, fi.frame_type),
segmentation: Default::default(),
restoration: rs,
frame_me_stats: FrameMEStats::new_arc_array(fi.w_in_b, fi.h_in_b),
Expand Down Expand Up @@ -539,6 +539,22 @@ pub struct DeblockState {
pub block_delta_multi: bool,
}

impl DeblockState {
pub fn new(config: &EncoderConfig, frame_type: FrameType) -> Self {
let mut state = DeblockState { ..Default::default() };
if frame_type == FrameType::INTER {
// Apply deblock strength only to inter frames
for level in &mut state.levels {
*level = ((*level as f32) * config.advanced_flags.deblock_strength)
.min(MAX_LOOP_FILTER as f32)
.round() as u8;
}
}
state.sharpness = config.advanced_flags.deblock_sharpness;
state
}
}

impl Default for DeblockState {
fn default() -> Self {
DeblockState {
Expand Down
1 change: 1 addition & 0 deletions src/fuzzing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ impl Arbitrary for ArbitraryEncoder {
switch_frame_interval: u.int_in_range(0..=3)?,
tune: *u.choose(&[Tune::Psnr, Tune::Psychovisual])?,
film_grain_params: None,
advanced_flags: Default::default(),
};

let frame_count =
Expand Down
Loading