try_again: false,
}
}
- fn encode_planes(&mut self, dbuf: &mut Vec<u8>, trees: &[Box<Indeo3PrimaryTree>], is_intra: bool) -> EncoderResult<()> {
+ fn encode_planes(&mut self, dbuf: &mut Vec<u8>, trees: &[Box<Indeo3PrimaryTree>], is_intra: bool) -> EncoderResult<bool> {
+ 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];
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);
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");
}
}
- Ok(())
+ Ok(zero)
}
}
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));
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 {
};
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)?;
}
}
}
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(())
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;
pub height: usize,
pub stripw: u8,
pub mvs: Vec<(MV, u16)>,
+ pub zero: bool,
}
fn ssd(a: u8, b: u8) -> u32 {
}
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) {
Indeo3PrimaryTree::AbsFill(sec) => {
iw.put_2bits(2);
cell.intra = true;
+ self.zero = false;
self.encode_sec(iw, cell, sec, cenc);
}
Indeo3PrimaryTree::RelFill(mv, sec) => {
} else {
iw.put_2bits(2);
cell.intra = true;
+ self.zero = false;
self.encode_sec(iw, cell, sec, cenc);
}
},
},
Indeo3SecondaryTree::VQData(mode) => {
iw.put_2bits(3);
+ self.zero = false;
self.encode_cell_data_intra(iw, cell, cenc, *mode);
},
}
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);
},
}