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