X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-indeo%2Fsrc%2Fcodecs%2Findeo3enc%2Fratectl.rs;fp=nihav-indeo%2Fsrc%2Fcodecs%2Findeo3enc%2Fratectl.rs;h=4bb74c0d32c935dbbd8a1c3c0c41a6f191c321bf;hp=0000000000000000000000000000000000000000;hb=77c25c7b24cc20357dff1bdacf8561e9ec1e57f2;hpb=4d965fde7928ba32b1f0f43cbc7d7a6c76446e46 diff --git a/nihav-indeo/src/codecs/indeo3enc/ratectl.rs b/nihav-indeo/src/codecs/indeo3enc/ratectl.rs new file mode 100644 index 0000000..4bb74c0 --- /dev/null +++ b/nihav-indeo/src/codecs/indeo3enc/ratectl.rs @@ -0,0 +1,77 @@ +#[derive(Default)] +pub struct RateControl { + bitrate: u32, + br_pool: u32, + f_pos: u32, + fracs: u32, + key_int: u32, + tb_num: u32, + tb_den: u32, + quality: Option, +} + +impl RateControl { + pub fn new() -> Self { Self{ key_int: 10, ..Default::default() } } + pub fn set_quality(&mut self, quality: u8) { + if quality > 0 { + self.quality = Some((quality - 1).min(15)); + } else { + self.quality = None; + } + } + pub fn set_bitrate(&mut self, br: u32, tb_num: u32, tb_den: u32) { + if tb_num > 0 && tb_den > 0 { + self.bitrate = br / 8; + self.tb_num = tb_num; + self.tb_den = tb_den; + } else { + self.bitrate = 0; + self.tb_num = 0; + self.tb_den = 0; + } + self.quality = Some(0); + self.reset(); + } + pub fn set_key_int(&mut self, key_int: u32) { + self.key_int = key_int; + self.reset(); + } + pub fn reset(&mut self) { + self.br_pool = self.bitrate; + self.f_pos = 0; + self.fracs = self.tb_den; + } + pub fn get_key_int(&self) -> u32 { self.key_int } + pub fn get_quant(&self, frameno: u32) -> (bool, Option) { + let is_intra = self.key_int == 0 || (frameno % self.key_int) == 0; + (is_intra, self.quality) + } + pub fn advance(&mut self, size: u32) { + if self.bitrate != 0 { + let expected = self.get_expected_size(); + let cur_quant = self.quality.unwrap_or(0); + if (size > expected + expected / 10) && (cur_quant < 7) { + self.quality = Some(cur_quant + 1); + } else if (size < expected - expected / 10) && (cur_quant > 0) { + self.quality = Some(cur_quant - 1); + } + + self.f_pos += self.tb_num; + while self.f_pos >= self.tb_den { + self.f_pos -= self.tb_den; + self.br_pool += self.bitrate; + self.fracs += self.tb_den; + } + self.fracs -= self.tb_num; + + self.br_pool = self.br_pool.saturating_sub(size).min(self.bitrate * 3); + } + } + pub fn get_expected_size(&self) -> u32 { + if self.bitrate != 0 { + self.br_pool * self.tb_num / self.fracs + } else { + 0 + } + } +}