From fab7982c9ba36d2d6118ab615ea4c62e3c460b43 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sun, 7 Sep 2025 18:59:17 +0200 Subject: [PATCH] indeo3enc: improve handling of skipped frames --- nihav-indeo/src/codecs/indeo3enc/mod.rs | 30 ++++++++++++--------- nihav-indeo/src/codecs/indeo3enc/ratectl.rs | 16 ++++++----- nihav-indeo/src/codecs/indeo3enc/tree.rs | 9 +++++++ 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/nihav-indeo/src/codecs/indeo3enc/mod.rs b/nihav-indeo/src/codecs/indeo3enc/mod.rs index 917b2a4..156418a 100644 --- a/nihav-indeo/src/codecs/indeo3enc/mod.rs +++ b/nihav-indeo/src/codecs/indeo3enc/mod.rs @@ -133,7 +133,8 @@ impl Indeo3Encoder { try_again: false, } } - fn encode_planes(&mut self, dbuf: &mut Vec, trees: &[Box], is_intra: bool) -> EncoderResult<()> { + fn encode_planes(&mut self, dbuf: &mut Vec, trees: &[Box], is_intra: bool) -> EncoderResult { + let mut zero = true; for (&planeno, tree) in PLANE_ORDER.iter().zip(trees.iter()) { let offset = dbuf.len(); let ref_plane = &self.pframe.plane[planeno]; @@ -149,6 +150,7 @@ impl Indeo3Encoder { let mut iw = Indeo3Writer::new(dbuf); self.cframe.plane[planeno].encode_tree(&mut iw, tree, &mut self.cenc, ref_plane); + zero &= self.cframe.plane[planeno].zero; drop(iw); while (dbuf.len() & 3) != 0 { dbuf.push(0); @@ -157,17 +159,21 @@ impl Indeo3Encoder { let plane_off = PLANE_OFFSETS + 4 * if planeno > 0 { planeno ^ 3 } else { 0 }; write_u32le(&mut dbuf[plane_off..], (offset - OS_HEADER_SIZE) as u32)?; } - - let mut checksum = 0; - for plane in self.cframe.plane.iter() { - checksum ^= plane.checksum(); + if zero { + // skip frame + dbuf.truncate(48); + } else { + let mut checksum = 0; + for plane in self.cframe.plane.iter() { + checksum ^= plane.checksum(); + } + write_u16le(&mut dbuf[26..], checksum * 2)?; } - write_u16le(&mut dbuf[26..], checksum * 2)?; let size = (dbuf.len() - OS_HEADER_SIZE) as u32; write_u32le(&mut dbuf[8..], self.frameno ^ HDR_FIELD_2 ^ FRMH_TAG ^ size)?; write_u32le(&mut dbuf[12..], size)?; - write_u32le(&mut dbuf[20..], size * 8)?; + write_u32le(&mut dbuf[20..], if !zero { size * 8 } else { 0x80 })?; if is_intra { dbuf.extend_from_slice(b"\x0d\x0aVer 3.99.00.00\x0d\x0a\x00"); @@ -176,7 +182,7 @@ impl Indeo3Encoder { } } - Ok(()) + Ok(zero) } } @@ -272,7 +278,7 @@ impl NAEncoder for Indeo3Encoder { write_u32le(&mut dbuf[20..], size * 8)?; let fsize = dbuf.len() as u32; - self.rc.advance(fsize); + self.rc.advance(fsize, true); self.frameno += 1; self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, false, dbuf)); @@ -352,7 +358,7 @@ impl NAEncoder for Indeo3Encoder { trees.push(tree); } - self.encode_planes(&mut dbuf, &trees, is_intra)?; + let mut skipped = self.encode_planes(&mut dbuf, &trees, is_intra)?; let cur_quant = self.cenc.quant.unwrap_or(42); if self.try_again && !is_intra && cur_quant < 8 { @@ -369,7 +375,7 @@ impl NAEncoder for Indeo3Encoder { }; self.cenc.quant = Some(new_quant); dbuf.truncate(OS_HEADER_SIZE + BITSTREAM_HEADER_SIZE); - self.encode_planes(&mut dbuf, &trees, is_intra)?; + skipped = self.encode_planes(&mut dbuf, &trees, is_intra)?; } } } @@ -389,7 +395,7 @@ impl NAEncoder for Indeo3Encoder { self.frameno += 1; let fsize = dbuf.len() as u32; - self.rc.advance(fsize); + self.rc.advance(fsize, skipped); self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, is_intra, dbuf)); Ok(()) diff --git a/nihav-indeo/src/codecs/indeo3enc/ratectl.rs b/nihav-indeo/src/codecs/indeo3enc/ratectl.rs index 4bb74c0..72bed26 100644 --- a/nihav-indeo/src/codecs/indeo3enc/ratectl.rs +++ b/nihav-indeo/src/codecs/indeo3enc/ratectl.rs @@ -46,14 +46,16 @@ impl RateControl { let is_intra = self.key_int == 0 || (frameno % self.key_int) == 0; (is_intra, self.quality) } - pub fn advance(&mut self, size: u32) { + pub fn advance(&mut self, size: u32, skipped: bool) { 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); + if !skipped { + 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; diff --git a/nihav-indeo/src/codecs/indeo3enc/tree.rs b/nihav-indeo/src/codecs/indeo3enc/tree.rs index d6346d9..6515a7e 100644 --- a/nihav-indeo/src/codecs/indeo3enc/tree.rs +++ b/nihav-indeo/src/codecs/indeo3enc/tree.rs @@ -143,6 +143,7 @@ pub struct Plane { pub height: usize, pub stripw: u8, pub mvs: Vec<(MV, u16)>, + pub zero: bool, } fn ssd(a: u8, b: u8) -> u32 { @@ -359,6 +360,7 @@ impl Plane { } pub fn encode_tree(&mut self, iw: &mut Indeo3Writer, tree: &Indeo3PrimaryTree, cenc: &mut CellEncoder, refp: &Plane) { let cell = Indeo3Cell::new(self.width, self.height); + self.zero = true; self.encode_pri(iw, cell, tree, cenc, refp); } fn encode_pri(&mut self, iw: &mut Indeo3Writer, mut cell: Indeo3Cell, tree: &Indeo3PrimaryTree, cenc: &mut CellEncoder, refp: &Plane) { @@ -378,6 +380,7 @@ impl Plane { Indeo3PrimaryTree::AbsFill(sec) => { iw.put_2bits(2); cell.intra = true; + self.zero = false; self.encode_sec(iw, cell, sec, cenc); } Indeo3PrimaryTree::RelFill(mv, sec) => { @@ -390,6 +393,7 @@ impl Plane { } else { iw.put_2bits(2); cell.intra = true; + self.zero = false; self.encode_sec(iw, cell, sec, cenc); } }, @@ -415,6 +419,7 @@ impl Plane { }, Indeo3SecondaryTree::VQData(mode) => { iw.put_2bits(3); + self.zero = false; self.encode_cell_data_intra(iw, cell, cenc, *mode); }, } @@ -431,11 +436,15 @@ impl Plane { iw.put_2bits(2); iw.put_2bits(*mode); cenc.read_mv_buffer(refp, cell, mv); + if mv.x != 0 || mv.y != 0 { + self.zero = false; + } cenc.null_mv(); cenc.put_buffer(self); }, Indeo3SecondaryTree::VQData(_mode) => { iw.put_2bits(3); + self.zero = false; self.encode_cell_data_inter(iw, cell, cenc, mv, refp); }, } -- 2.39.5