use super::{
libaom_cq_for_target, nvenc_cq_for_target, piecewise_quality, tile_grid_hw, tile_grid_nvenc,
tile_grid_rav1e, NV_ENC_PRESET_P5_GUID_BYTES, NV_ENC_PRESET_P6_GUID_BYTES,
NV_ENC_PRESET_P7_GUID_BYTES, NVENC_TUNING_HIGH_QUALITY,
};
use super::params::{
AmfAv1Params, AmfQualityPreset, AmfRateControl, MFX_CODINGOPTION_ON, NvencAv1Params,
NvencRateControl, QsvAv1Params, QsvRateControl, Rav1eParams,
};
use super::{QualityTarget, SpeedTier};
pub fn rav1e_params(
target: QualityTarget,
tier: SpeedTier,
width: u32,
height: u32,
) -> Rav1eParams {
let libaom_cq = libaom_cq_for_target(target);
let quantizer = (libaom_cq as usize) * 4;
let speed_preset = match tier {
SpeedTier::Archive => 4,
SpeedTier::Standard => 6,
SpeedTier::Draft => 8,
};
let (tile_cols, tile_rows) = tile_grid_rav1e(width, height);
Rav1eParams {
quantizer,
speed_preset,
tile_rows,
tile_cols,
}
}
pub fn nvenc_av1_params(
target: QualityTarget,
tier: SpeedTier,
width: u32,
height: u32,
) -> NvencAv1Params {
let cq = nvenc_cq_for_target(target);
let (preset_guid, lookahead_depth, aq_strength) = match tier {
SpeedTier::Archive => (NV_ENC_PRESET_P7_GUID_BYTES, 32, 10),
SpeedTier::Standard => (NV_ENC_PRESET_P6_GUID_BYTES, 16, 8),
SpeedTier::Draft => (NV_ENC_PRESET_P5_GUID_BYTES, 0, 6),
};
let rc_mode = match target {
QualityTarget::VisuallyLossless => NvencRateControl::ConstQp,
_ => NvencRateControl::VbrTargetQuality,
};
let (num_tile_columns, num_tile_rows) = tile_grid_nvenc(width, height);
NvencAv1Params {
rc_mode,
cq,
preset_guid,
tuning_info: NVENC_TUNING_HIGH_QUALITY,
aq_strength,
lookahead_depth,
num_tile_columns: num_tile_columns as u32,
num_tile_rows: num_tile_rows as u32,
output_annex_b_format: 0, repeat_seq_hdr: 1,
}
}
pub fn amf_av1_params(
target: QualityTarget,
tier: SpeedTier,
width: u32,
height: u32,
) -> AmfAv1Params {
let q_index_intra = amf_q_index_for_target(target);
let q_index_inter = q_index_intra.saturating_add(8);
let qvbr_quality = match target {
QualityTarget::VisuallyLossless => 95,
QualityTarget::High => 85,
QualityTarget::Standard => 70,
QualityTarget::Low => 55,
QualityTarget::Vmaf(v) => vmaf_to_qvbr_quality(v),
};
let quality_preset = match tier {
SpeedTier::Archive => AmfQualityPreset::HighQuality,
SpeedTier::Standard => AmfQualityPreset::Quality,
SpeedTier::Draft => AmfQualityPreset::Balanced,
};
let rc_mode = match target {
QualityTarget::VisuallyLossless => AmfRateControl::Cqp,
_ => AmfRateControl::QualityVbr,
};
let (tile_cols, tile_rows) = tile_grid_hw(width, height);
let tiles_per_frame = (tile_cols * tile_rows) as u32;
AmfAv1Params {
rc_mode,
q_index_intra,
q_index_inter,
qvbr_quality,
quality_preset,
gop_size: 0, aq_mode: 1, tiles_per_frame,
}
}
fn amf_q_index_for_target(target: QualityTarget) -> u8 {
let base = match target {
QualityTarget::VisuallyLossless => 72, QualityTarget::High => 100, QualityTarget::Standard => 120, QualityTarget::Low => 144, QualityTarget::Vmaf(v) => vmaf_to_amf_q_index(v),
};
base.min(255) as u8
}
const AMF_Q_INDEX_ANCHORS: &[(i32, i32)] = &[
(100, 50), (98, 72),
(95, 100),
(90, 120),
(85, 144),
(70, 200),
];
fn vmaf_to_amf_q_index(vmaf: u8) -> u16 {
piecewise_quality(vmaf, AMF_Q_INDEX_ANCHORS, 0, 255) as u16
}
const AMF_QVBR_ANCHORS: &[(i32, i32)] =
&[(100, 100), (98, 95), (95, 85), (90, 70), (85, 55), (70, 35)];
fn vmaf_to_qvbr_quality(vmaf: u8) -> u8 {
piecewise_quality(vmaf, AMF_QVBR_ANCHORS, 1, 100)
}
pub fn qsv_av1_params(
target: QualityTarget,
tier: SpeedTier,
width: u32,
height: u32,
) -> QsvAv1Params {
let icq_quality = match target {
QualityTarget::VisuallyLossless => 16,
QualityTarget::High => 22,
QualityTarget::Standard => 26,
QualityTarget::Low => 31,
QualityTarget::Vmaf(v) => vmaf_to_qsv_icq(v),
};
let libaom_cq = libaom_cq_for_target(target);
let qp_i = (libaom_cq as u16 * 4).min(255);
let qp_p = qp_i.saturating_add(8).min(255);
let target_usage = match tier {
SpeedTier::Archive => 1,
SpeedTier::Standard => 4,
SpeedTier::Draft => 6,
};
let rc_mode = match target {
QualityTarget::VisuallyLossless => QsvRateControl::Cqp,
_ => QsvRateControl::Icq,
};
let (num_tile_columns, num_tile_rows) = tile_grid_hw(width, height);
QsvAv1Params {
rc_mode,
icq_quality,
qp_i,
qp_p,
target_usage,
gop_pic_size: 0, num_tile_columns: num_tile_columns as u8,
num_tile_rows: num_tile_rows as u8,
low_power: MFX_CODINGOPTION_ON,
}
}
const QSV_ICQ_ANCHORS: &[(i32, i32)] =
&[(100, 8), (98, 18), (95, 24), (90, 30), (85, 36), (70, 48)];
fn vmaf_to_qsv_icq(vmaf: u8) -> u16 {
piecewise_quality(vmaf, QSV_ICQ_ANCHORS, 1, 51) as u16
}