1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
use super::BlockMode;
#[derive(Default)]
pub struct RateControl {
bitrate: u32,
bitpool: u32,
tb_num: u32,
tb_den: u32,
fpos: u32,
quality: u8,
lambda: f32,
first: bool,
}
impl RateControl {
pub fn new() -> Self {
Self {
lambda: 1.0,
..Default::default()
}
}
pub fn init(&mut self, tb_num: u32, tb_den: u32, bitrate: u32, quality: u8) {
self.tb_num = tb_num;
self.tb_den = tb_den;
self.bitrate = bitrate;
self.quality = quality;
self.bitpool = self.bitrate;
self.fpos = 0;
self.first = true;
}
pub fn metric(&self, diff: u32, bits: usize) -> u32 {
diff.saturating_add((self.get_weight() * (bits as f32)) as u32)
}
fn get_weight(&self) -> f32 {
if (0..=100).contains(&self.quality) {
self.lambda * ((100 - self.quality) as f32)
} else {
self.lambda
}
}
pub fn expected_size(&self) -> u32 {
if self.bitrate != 0 {
(if !self.first {
let ticks = self.tb_den - self.fpos;
u64::from(self.bitpool) * u64::from(self.tb_num) / u64::from(ticks)
} else {
u64::from(self.bitrate) * 4 * u64::from(self.tb_num) / u64::from(self.tb_den)
}) as u32
} else {
0
}
}
pub fn update_size(&mut self, real_size: usize) {
if self.bitrate != 0 {
let bits = (real_size * 8) as u32;
let tgt_size = self.expected_size();
self.fpos += self.tb_num;
while self.fpos >= self.tb_den {
self.fpos -= self.tb_den;
self.bitpool += self.bitrate;
}
self.bitpool = self.bitpool.saturating_sub(bits);
if bits > tgt_size + tgt_size / 8 {
self.lambda += 0.1;
}
if bits < tgt_size - tgt_size / 8 {
self.lambda -= 0.1;
if self.lambda < 0.0 {
self.lambda = 0.0;
}
}
self.first = false;
}
}
pub fn pattern_run_threshold(&self) -> u8 {
match self.quality {
1..=39 => 4,
40..=59 => 3,
60..=79 => 2,
80..=89 => 1,
_ => 0,
}
}
pub fn get_quant_ranges(&self) -> [u8; 4] {
match self.quality {
98..=100 => [ 0, 0, 0, 2 ],
92..=97 => [ 2, 16, 4, 16 ],
85..=91 => [ 5, 16, 7, 16 ],
75..=84 => [ 8, 16, 10, 16 ],
55..=74 => [ 11, 16, 12, 16 ],
1..=54 => [ 12, 16, 13, 16 ],
_ => [ 0, 16, 0, 16 ],
}
}
pub fn modify_forbidden_btypes(&self, forbidden: &mut [bool; 12]) {
if self.quality > 98 {
forbidden[usize::from(BlockMode::Intra)] = true;
}
if self.quality > 0 {
if self.quality < 80 {
forbidden[usize::from(BlockMode::Run)] = true;
forbidden[usize::from(BlockMode::Residue)] = true;
}
if self.quality < 90 {
forbidden[usize::from(BlockMode::Raw)] = true;
}
}
}
}
|