4 static mut COUNTER: usize = 0;
6 pub const SMALL_DIST: u32 = 256;
7 pub const MAX_DIST: u32 = std::u32::MAX;
9 const INTER_TO_INTRA_RATIO: f32 = 0.85;
11 pub struct RateDistMetric {
16 pub fn new() -> Self {
21 pub fn calc_metric(&self, dist: u32, nits: u32) -> u32 {
22 ((dist as f32) + self.lambda * (nits as f32) + 0.5) as u32
24 pub fn adjust_br(&mut self, cur_size: usize, tgt_size: usize) {
25 let low_limit = tgt_size - tgt_size / 8;
26 let up_limit = tgt_size + tgt_size / 8;
27 if cur_size < low_limit {
28 self.lambda = (self.lambda - 0.1).max(0.0);
29 } else if cur_size > up_limit {
30 self.lambda = (self.lambda + 0.1).min(16.0);
34 pub fn block_dist(&self, src: &[u8; 16], new: &[u8; 16], q: usize, ctype: usize, pctx: u8, probs: &[[[u8; 11]; 3]; 8]) -> (u32, bool) {
35 let mut diff = [0i16; 16];
36 get_block_difference(&mut diff, src, new);
39 let has_nz = diff.has_nz();
40 let nits = estimate_subblock_nits(&diff, ctype, pctx, probs);
41 diff.dequant(q, ctype);
43 let dist = get_difference_dist(src, new, &diff);
44 unsafe {COUNTER += 1;}
45 (self.calc_metric(dist, nits), has_nz)
50 pub struct BitRateControl {
55 force_q: Option<usize>,
63 pub fn new() -> Self { Self::default() }
67 self.bitpool = self.bitrate;
69 pub fn set_params(&mut self, tb_num: u32, tb_den: u32, bitrate: u32, key_int: u8, num_mb: usize) {
72 self.bitrate = bitrate;
73 self.key_int = u32::from(key_int);
74 self.num_mb = num_mb as u32;
77 pub fn has_bitrate(&self) -> bool { self.bitrate != 0 }
78 pub fn get_quant(&self) -> Option<usize> { self.force_q }
79 pub fn set_quant(&mut self, q: Option<usize>) {
80 if self.force_q != q {
85 pub fn set_key_interval(&mut self, key_int: u8) {
86 let key_int = u32::from(key_int);
87 if self.key_int != key_int {
88 self.key_int = key_int;
92 pub fn get_target_size(&self, is_intra: bool) -> u32 {
93 if self.bitrate != 0 && self.force_q.is_none() {
94 let pool_frames = self.tb_den - self.fpos;
95 if self.key_int <= 1 { // all intra
96 if self.bitpool == 0 || pool_frames == 0 {
97 self.bitrate * self.tb_num / self.tb_den
99 self.bitpool / pool_frames
102 let full_gop_weight = 1.0 + ((self.key_int - 1) as f32) * INTER_TO_INTRA_RATIO;
103 let i_bits = if self.bitpool == 0 || pool_frames == 0 {
104 let gop_size = self.bitrate * self.tb_num * self.key_int / self.tb_den;
105 (gop_size as f32) / full_gop_weight
107 let full_gops = pool_frames / self.key_int;
108 let weight = (full_gops as f32) * full_gop_weight + ((pool_frames % self.key_int) as f32) * INTER_TO_INTRA_RATIO;
109 (self.bitpool as f32) / weight
112 (i_bits + 0.5) as u32
114 (i_bits * INTER_TO_INTRA_RATIO + 0.5) as u32
121 fn pred_nits_per_mb(is_intra: bool, q: usize) -> f32 {
123 match (is_intra, q) {
124 (true, 0..=6) => 3434.0 + fq * fq * 7.5 - fq * 195.0,
125 (true, _) => 2500.0 - (fq - 6.0).ln() * 500.0,
126 (false, 0..=10) => 1595.0 + fq * fq * 3.4 - fq * 125.0,
127 (false, _) => 800.0 - (fq - 8.0).ln() * 155.0,
131 // todo use for refining maybe
132 pub fn predict_size(&self, is_intra: bool, q: usize) -> u32 {
133 let min_size = if is_intra { 200 * 8 } else { 50 * 8 };
134 let nits_per_mb = Self::pred_nits_per_mb(is_intra, q);
135 ((nits_per_mb * (self.num_mb as f32) / 8.0) as u32).max(min_size)
137 pub fn get_frame_quant(&self, is_intra: bool) -> usize {
138 if let Some(q) = self.force_q {
141 let expected_size = self.get_target_size(is_intra);
142 let nits_per_mb = ((expected_size * 8) as f32) / (self.num_mb as f32);
144 if nits_per_mb > 2500.0 { // simple search
145 if nits_per_mb > Self::pred_nits_per_mb(is_intra, 3) {
146 if nits_per_mb > Self::pred_nits_per_mb(is_intra, 1) {
148 } else if nits_per_mb > Self::pred_nits_per_mb(is_intra, 2) {
154 if nits_per_mb > Self::pred_nits_per_mb(is_intra, 4) {
156 } else if nits_per_mb > Self::pred_nits_per_mb(is_intra, 5) {
163 ((((2500.0 - nits_per_mb) / 500.0).exp() + 6.0) as usize).min(127)
166 if nits_per_mb > 680.0 { // simple search
167 let (start, end) = if nits_per_mb > Self::pred_nits_per_mb(is_intra, 5) {
168 if nits_per_mb > Self::pred_nits_per_mb(is_intra, 3) {
173 } else if nits_per_mb > Self::pred_nits_per_mb(is_intra, 7) {
179 for qq in start..end {
180 if nits_per_mb > Self::pred_nits_per_mb(is_intra, qq) {
187 ((((800.0 - nits_per_mb) / 155.0).exp() + 6.0) as usize).max(10).min(127)
192 pub fn update(&mut self, size: usize) {
194 if self.kpos == self.key_int {
197 if self.bitrate == 0 || self.force_q.is_some() {
200 self.fpos += self.tb_num;
201 while self.fpos >= self.tb_den {
202 self.fpos -= self.tb_den;
203 self.bitpool += self.bitrate;
205 self.bitpool = self.bitpool.saturating_sub((size * 8) as u32);