use super::super::config::ProgressiveScan;
#[derive(Debug, Clone)]
pub(crate) struct ScanSearchConfig {
pub al_max_luma: u8,
pub al_max_chroma: u8,
pub frequency_splits: [u8; 5],
pub dc_scan_opt_mode: u8,
}
impl Default for ScanSearchConfig {
fn default() -> Self {
Self {
al_max_luma: 3,
al_max_chroma: 2,
frequency_splits: [2, 8, 5, 12, 18],
dc_scan_opt_mode: 1,
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct ScanSearchResult {
pub best_al_luma: u8,
pub best_al_chroma: u8,
pub best_freq_split_luma: usize,
pub best_freq_split_chroma: usize,
pub interleave_chroma_dc: bool,
}
impl ScanSearchResult {
pub fn build_final_scans(
&self,
num_components: u8,
config: &ScanSearchConfig,
) -> Vec<ProgressiveScan> {
let mut scans = Vec::new();
if config.dc_scan_opt_mode == 0 {
let components: Vec<u8> = (0..num_components).collect();
scans.push(ProgressiveScan {
components,
ss: 0,
se: 0,
ah: 0,
al: 0,
});
} else {
scans.push(ProgressiveScan {
components: vec![0],
ss: 0,
se: 0,
ah: 0,
al: 0,
});
}
let al = self.best_al_luma;
if al == 0 && self.best_freq_split_luma > 0 {
let split = config.frequency_splits[self.best_freq_split_luma - 1];
scans.push(ProgressiveScan {
components: vec![0],
ss: 1,
se: split,
ah: 0,
al: 0,
});
scans.push(ProgressiveScan {
components: vec![0],
ss: split + 1,
se: 63,
ah: 0,
al: 0,
});
} else {
scans.push(ProgressiveScan {
components: vec![0],
ss: 1,
se: 63,
ah: 0,
al,
});
}
for refine_al in (0..al).rev() {
scans.push(ProgressiveScan {
components: vec![0],
ss: 1,
se: 63,
ah: refine_al + 1,
al: refine_al,
});
}
if num_components >= 3 {
if config.dc_scan_opt_mode != 0 {
if self.interleave_chroma_dc {
scans.push(ProgressiveScan {
components: vec![1, 2],
ss: 0,
se: 0,
ah: 0,
al: 0,
});
} else {
for c in 1..=2u8 {
scans.push(ProgressiveScan {
components: vec![c],
ss: 0,
se: 0,
ah: 0,
al: 0,
});
}
}
}
let al_c = self.best_al_chroma;
for comp in 1..=2u8 {
if al_c == 0 && self.best_freq_split_chroma > 0 {
let split = config.frequency_splits[self.best_freq_split_chroma - 1];
scans.push(ProgressiveScan {
components: vec![comp],
ss: 1,
se: split,
ah: 0,
al: 0,
});
scans.push(ProgressiveScan {
components: vec![comp],
ss: split + 1,
se: 63,
ah: 0,
al: 0,
});
} else {
scans.push(ProgressiveScan {
components: vec![comp],
ss: 1,
se: 63,
ah: 0,
al: al_c,
});
}
}
for refine_al in (0..al_c).rev() {
for comp in 1..=2u8 {
scans.push(ProgressiveScan {
components: vec![comp],
ss: 1,
se: 63,
ah: refine_al + 1,
al: refine_al,
});
}
}
}
scans
}
}