use num_derive::*;
use crate::partition::BlockSize;
use crate::serialize::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct SpeedSettings {
pub multiref: bool,
pub fast_deblock: bool,
pub reduced_tx_set: bool,
pub tx_domain_distortion: bool,
pub tx_domain_rate: bool,
pub encode_bottomup: bool,
pub rdo_tx_decision: bool,
pub prediction_modes: PredictionModesSetting,
pub include_near_mvs: bool,
pub no_scene_detection: bool,
pub fast_scene_detection: bool,
pub cdef: bool,
pub lrf: bool,
pub sgr_complexity: SGRComplexityLevel,
pub use_satd_subpel: bool,
pub non_square_partition: bool,
pub enable_segmentation: bool,
pub enable_inter_tx_split: bool,
pub fine_directional_intra: bool,
pub partition_range: PartitionRange,
}
impl Default for SpeedSettings {
fn default() -> Self {
SpeedSettings {
partition_range: PartitionRange::new(
BlockSize::BLOCK_4X4,
BlockSize::BLOCK_64X64,
),
multiref: true,
fast_deblock: false,
reduced_tx_set: false,
tx_domain_distortion: false,
tx_domain_rate: false,
encode_bottomup: true,
rdo_tx_decision: true,
prediction_modes: PredictionModesSetting::ComplexAll,
include_near_mvs: true,
no_scene_detection: false,
fast_scene_detection: false,
cdef: true,
lrf: false,
sgr_complexity: SGRComplexityLevel::Full,
use_satd_subpel: true,
non_square_partition: true,
enable_segmentation: true,
enable_inter_tx_split: false,
fine_directional_intra: false,
}
}
}
impl SpeedSettings {
pub fn from_preset(speed: usize) -> Self {
SpeedSettings {
partition_range: Self::partition_range_preset(speed),
multiref: Self::multiref_preset(speed),
fast_deblock: Self::fast_deblock_preset(speed),
reduced_tx_set: Self::reduced_tx_set_preset(speed),
tx_domain_distortion: Self::tx_domain_distortion_preset(speed),
tx_domain_rate: Self::tx_domain_rate_preset(speed),
encode_bottomup: Self::encode_bottomup_preset(speed),
rdo_tx_decision: Self::rdo_tx_decision_preset(speed),
prediction_modes: Self::prediction_modes_preset(speed),
include_near_mvs: Self::include_near_mvs_preset(speed),
no_scene_detection: Self::no_scene_detection_preset(speed),
fast_scene_detection: Self::fast_scene_detection_preset(speed),
cdef: Self::cdef_preset(speed),
lrf: Self::lrf_preset(speed),
sgr_complexity: Self::sgr_complexity_preset(speed),
use_satd_subpel: Self::use_satd_subpel(speed),
non_square_partition: Self::non_square_partition_preset(speed),
enable_segmentation: Self::enable_segmentation_preset(speed),
enable_inter_tx_split: Self::enable_inter_tx_split_preset(speed),
fine_directional_intra: Self::fine_directional_intra_preset(speed),
}
}
fn partition_range_preset(speed: usize) -> PartitionRange {
if speed <= 2 {
PartitionRange::new(BlockSize::BLOCK_4X4, BlockSize::BLOCK_64X64)
} else if speed <= 8 {
PartitionRange::new(BlockSize::BLOCK_8X8, BlockSize::BLOCK_64X64)
} else if speed <= 9 {
PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_64X64)
} else {
PartitionRange::new(BlockSize::BLOCK_32X32, BlockSize::BLOCK_32X32)
}
}
const fn multiref_preset(speed: usize) -> bool {
speed <= 7
}
const fn fast_deblock_preset(speed: usize) -> bool {
speed >= 8
}
const fn reduced_tx_set_preset(speed: usize) -> bool {
speed >= 6
}
const fn tx_domain_distortion_preset(_speed: usize) -> bool {
true
}
const fn tx_domain_rate_preset(_speed: usize) -> bool {
false
}
const fn encode_bottomup_preset(speed: usize) -> bool {
speed <= 1
}
const fn rdo_tx_decision_preset(speed: usize) -> bool {
speed <= 5
}
fn prediction_modes_preset(speed: usize) -> PredictionModesSetting {
if speed <= 2 {
PredictionModesSetting::ComplexAll
} else if speed <= 6 {
PredictionModesSetting::ComplexKeyframes
} else {
PredictionModesSetting::Simple
}
}
const fn include_near_mvs_preset(speed: usize) -> bool {
speed <= 3
}
const fn no_scene_detection_preset(_speed: usize) -> bool {
false
}
const fn fast_scene_detection_preset(speed: usize) -> bool {
speed == 10
}
const fn cdef_preset(_speed: usize) -> bool {
true
}
const fn lrf_preset(speed: usize) -> bool {
speed <= 9
}
fn sgr_complexity_preset(speed: usize) -> SGRComplexityLevel {
if speed <= 4 {
SGRComplexityLevel::Full
} else {
SGRComplexityLevel::Reduced
}
}
const fn use_satd_subpel(speed: usize) -> bool {
speed <= 9
}
const fn non_square_partition_preset(speed: usize) -> bool {
speed == 0
}
const fn enable_segmentation_preset(speed: usize) -> bool {
speed == 0
}
const fn enable_inter_tx_split_preset(speed: usize) -> bool {
speed >= 9
}
fn fine_directional_intra_preset(_speed: usize) -> bool {
true
}
}
#[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 }
}
}
#[derive(
Clone,
Copy,
Debug,
PartialOrd,
PartialEq,
FromPrimitive,
Serialize,
Deserialize,
)]
pub enum PredictionModesSetting {
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,
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",
}
)
}
}