pito_codecs/vp9/enc/rc/
aq.rs1use super::q::{q_index_for, qstep};
2
3pub const SEGMENTS: usize = 8;
4const SCALE: [f64; SEGMENTS] = [0.76, 0.82, 0.88, 0.94, 1.0, 1.06, 1.13, 1.2];
5const STRENGTH: f64 = 0.12;
6
7#[derive(Clone, Debug, Default)]
8pub struct Segmentation {
9 pub enabled: bool,
10 pub update_map: bool,
11 pub update_data: bool,
12 pub abs_delta: bool,
13 pub tree_probs: [u8; 7],
14 pub q: [i16; SEGMENTS],
15 pub lf: [i8; SEGMENTS],
16 pub map: Vec<u8>,
17 pub mi_cols: usize,
18 pub mi_rows: usize,
19 block_seg: Vec<u8>,
20}
21
22impl Segmentation {
23 pub fn segment(&self, mi_row: usize, mi_col: usize) -> u8 {
24 if !self.enabled {
25 return 0;
26 }
27 self.map[mi_row * self.mi_cols + mi_col]
28 }
29
30 pub fn q_index(&self, base: u8, seg: u8) -> u8 {
31 if !self.enabled {
32 return base;
33 }
34 let q = self.q[seg as usize] as i32;
35 if self.abs_delta {
36 q.clamp(0, 255) as u8
37 } else {
38 (base as i32 + q).clamp(0, 255) as u8
39 }
40 }
41
42 pub fn disable(&mut self) {
43 self.enabled = false;
44 self.update_map = false;
45 self.update_data = false;
46 }
47
48 pub fn variance_aq(
49 &mut self,
50 base_q: u8,
51 mi_cols: usize,
52 mi_rows: usize,
53 activity: &[u32],
54 blocks: (usize, usize),
55 ) {
56 let (bw, bh) = blocks;
57 if base_q < 8 || bw * bh == 0 {
58 self.disable();
59 return;
60 }
61 let n = (bw * bh) as f64;
62 let mean_log = activity
63 .iter()
64 .map(|&a| ((a + 16) as f64).ln())
65 .sum::<f64>()
66 / n;
67 let base_step = qstep(base_q);
68 let mut q = [0i16; SEGMENTS];
69 let mut prev = i32::MIN;
70 for (s, scale) in SCALE.iter().enumerate() {
71 let qi = (q_index_for(base_step * scale) as i32)
72 .clamp(1, 255)
73 .max(prev);
74 prev = qi;
75 q[s] = (qi - base_q as i32) as i16;
76 }
77 let edges: [f64; SEGMENTS - 1] =
78 std::array::from_fn(|i| ((SCALE[i] * SCALE[i + 1]).sqrt().ln()) / STRENGTH);
79 let mut block_seg = std::mem::take(&mut self.block_seg);
80 block_seg.resize(bw * bh, 0);
81 for (seg, &a) in block_seg.iter_mut().zip(activity) {
82 let d = ((a + 16) as f64).ln() - mean_log;
83 *seg = edges.partition_point(|&e| e < d) as u8;
84 }
85 self.map.resize(mi_cols * mi_rows, 0);
86 let mut counts = [0u32; SEGMENTS];
87 for r in 0..mi_rows {
88 let by = (r / 2).min(bh - 1);
89 let row = &mut self.map[r * mi_cols..][..mi_cols];
90 for (c, m) in row.iter_mut().enumerate() {
91 let s = block_seg[by * bw + (c / 2).min(bw - 1)];
92 *m = s;
93 counts[s as usize] += 1;
94 }
95 }
96 self.block_seg = block_seg;
97 self.enabled = true;
98 self.update_map = true;
99 self.update_data = true;
100 self.abs_delta = false;
101 self.q = q;
102 self.lf = [0; SEGMENTS];
103 self.mi_cols = mi_cols;
104 self.mi_rows = mi_rows;
105 self.tree_probs = tree_probs(&counts);
106 }
107}
108
109pub fn tree_probs(c: &[u32; SEGMENTS]) -> [u8; 7] {
110 let p = |l: u32, r: u32| {
111 let t = l + r;
112 if t == 0 {
113 255
114 } else {
115 ((l as u64 * 256 + t as u64 / 2) / t as u64).clamp(1, 255) as u8
116 }
117 };
118 [
119 p(c[0] + c[1] + c[2] + c[3], c[4] + c[5] + c[6] + c[7]),
120 p(c[0] + c[1], c[2] + c[3]),
121 p(c[4] + c[5], c[6] + c[7]),
122 p(c[0], c[1]),
123 p(c[2], c[3]),
124 p(c[4], c[5]),
125 p(c[6], c[7]),
126 ]
127}