use num_derive::*;
use crate::partition::BlockSize;
use crate::serialize::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct SpeedSettings {
pub multiref: bool,
pub fast_deblock: bool,
pub rdo_lookahead_frames: usize,
pub scene_detection_mode: SceneDetectionSpeed,
pub cdef: bool,
pub lrf: bool,
pub lru_on_skip: bool,
pub sgr_complexity: SGRComplexityLevel,
pub segmentation: SegmentationLevel,
pub partition: PartitionSpeedSettings,
pub transform: TransformSpeedSettings,
pub prediction: PredictionSpeedSettings,
pub motion: MotionSpeedSettings,
}
impl Default for SpeedSettings {
fn default() -> Self {
SpeedSettings {
multiref: true,
fast_deblock: false,
rdo_lookahead_frames: 40,
scene_detection_mode: SceneDetectionSpeed::Standard,
cdef: true,
lrf: true,
lru_on_skip: true,
sgr_complexity: SGRComplexityLevel::Full,
segmentation: SegmentationLevel::Complex,
partition: PartitionSpeedSettings {
encode_bottomup: true,
non_square_partition_max_threshold: BlockSize::BLOCK_64X64,
partition_range: PartitionRange::new(
BlockSize::BLOCK_4X4,
BlockSize::BLOCK_64X64,
),
},
transform: TransformSpeedSettings {
reduced_tx_set: false,
tx_domain_distortion: true,
tx_domain_rate: false,
rdo_tx_decision: true,
enable_inter_tx_split: false,
},
prediction: PredictionSpeedSettings {
prediction_modes: PredictionModesSetting::ComplexAll,
fine_directional_intra: true,
},
motion: MotionSpeedSettings {
include_near_mvs: true,
use_satd_subpel: true,
me_allow_full_search: true,
},
}
}
}
impl SpeedSettings {
pub fn from_preset(speed: u8) -> Self {
let mut settings = SpeedSettings::default();
if speed >= 1 {
settings.lru_on_skip = false;
settings.segmentation = SegmentationLevel::Simple;
}
if speed >= 2 {
settings.partition.non_square_partition_max_threshold =
BlockSize::BLOCK_8X8;
settings.prediction.prediction_modes =
PredictionModesSetting::ComplexKeyframes;
}
if speed >= 3 {
settings.rdo_lookahead_frames = 30;
settings.partition.partition_range =
PartitionRange::new(BlockSize::BLOCK_8X8, BlockSize::BLOCK_64X64);
}
if speed >= 4 {
settings.partition.encode_bottomup = false;
}
if speed >= 5 {
settings.sgr_complexity = SGRComplexityLevel::Reduced;
settings.motion.include_near_mvs = false;
}
if speed >= 6 {
settings.rdo_lookahead_frames = 20;
settings.transform.rdo_tx_decision = false;
settings.transform.reduced_tx_set = true;
settings.motion.me_allow_full_search = false;
}
if speed >= 7 {
settings.prediction.prediction_modes = PredictionModesSetting::Simple;
settings.multiref = false;
settings.fast_deblock = true;
}
if speed >= 8 {
settings.rdo_lookahead_frames = 10;
settings.lrf = false;
}
if speed >= 9 {
settings.partition.partition_range =
PartitionRange::new(BlockSize::BLOCK_16X16, BlockSize::BLOCK_32X32);
settings.transform.enable_inter_tx_split = true;
}
if speed >= 10 {
settings.scene_detection_mode = SceneDetectionSpeed::Fast;
settings.partition.partition_range =
PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_32X32);
settings.motion.use_satd_subpel = false;
}
settings
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[cfg_attr(test, derive(Default))]
pub struct TransformSpeedSettings {
pub reduced_tx_set: bool,
pub tx_domain_distortion: bool,
pub tx_domain_rate: bool,
pub rdo_tx_decision: bool,
pub enable_inter_tx_split: bool,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[cfg_attr(test, derive(Default))]
pub struct PartitionSpeedSettings {
pub encode_bottomup: bool,
pub non_square_partition_max_threshold: BlockSize,
pub partition_range: PartitionRange,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[cfg_attr(test, derive(Default))]
pub struct MotionSpeedSettings {
pub use_satd_subpel: bool,
pub include_near_mvs: bool,
pub me_allow_full_search: bool,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[cfg_attr(test, derive(Default))]
pub struct PredictionSpeedSettings {
pub prediction_modes: PredictionModesSetting,
pub fine_directional_intra: bool,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct PartitionRange {
pub(crate) min: BlockSize,
pub(crate) max: BlockSize,
}
impl PartitionRange {
pub fn new(min: BlockSize, max: BlockSize) -> Self {
assert!(max >= min);
assert!(min.is_sqr());
assert!(max.is_sqr());
Self { min, max }
}
}
#[cfg(test)]
impl Default for PartitionRange {
fn default() -> Self {
PartitionRange::new(BlockSize::BLOCK_4X4, BlockSize::BLOCK_64X64)
}
}
#[derive(
Clone,
Copy,
Debug,
PartialOrd,
PartialEq,
Eq,
FromPrimitive,
Serialize,
Deserialize,
)]
pub enum SceneDetectionSpeed {
Fast,
Standard,
None,
}
impl fmt::Display for SceneDetectionSpeed {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
f,
"{}",
match self {
SceneDetectionSpeed::Fast => "Fast",
SceneDetectionSpeed::Standard => "Standard",
SceneDetectionSpeed::None => "None",
}
)
}
}
#[derive(
Clone,
Copy,
Debug,
PartialOrd,
PartialEq,
Eq,
FromPrimitive,
Serialize,
Deserialize,
)]
#[cfg_attr(test, derive(Default))]
pub enum PredictionModesSetting {
#[cfg_attr(test, default)]
Simple,
ComplexKeyframes,
ComplexAll,
}
impl fmt::Display for PredictionModesSetting {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
f,
"{}",
match self {
PredictionModesSetting::Simple => "Simple",
PredictionModesSetting::ComplexKeyframes => "Complex-KFs",
PredictionModesSetting::ComplexAll => "Complex-All",
}
)
}
}
#[derive(
Clone,
Copy,
Debug,
PartialOrd,
PartialEq,
Eq,
FromPrimitive,
Serialize,
Deserialize,
)]
pub enum SGRComplexityLevel {
Full,
Reduced,
}
impl fmt::Display for SGRComplexityLevel {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
f,
"{}",
match self {
SGRComplexityLevel::Full => "Full",
SGRComplexityLevel::Reduced => "Reduced",
}
)
}
}
#[derive(
Clone,
Copy,
Debug,
PartialOrd,
PartialEq,
Eq,
FromPrimitive,
Serialize,
Deserialize,
)]
pub enum SegmentationLevel {
Disabled,
Simple,
Complex,
Full,
}
impl fmt::Display for SegmentationLevel {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
f,
"{}",
match self {
SegmentationLevel::Disabled => "Disabled",
SegmentationLevel::Simple => "Simple",
SegmentationLevel::Complex => "Complex",
SegmentationLevel::Full => "Full",
}
)
}
}