X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-commonfmt%2Fsrc%2Fcodecs%2Fcinepakenc.rs;h=95994eedae1f73dd2107841a29c52b1fd88371b3;hp=d258df97114c1014eedbe2a4a72894d7cc0f23c9;hb=78fb6560c73965d834b215fb0b49505ae5443288;hpb=6bc499a08e97a9dc27955faf3fdcf8a206e9991a diff --git a/nihav-commonfmt/src/codecs/cinepakenc.rs b/nihav-commonfmt/src/codecs/cinepakenc.rs index d258df9..95994ee 100644 --- a/nihav-commonfmt/src/codecs/cinepakenc.rs +++ b/nihav-commonfmt/src/codecs/cinepakenc.rs @@ -218,7 +218,7 @@ enum QuantMode { MedianCut, } -impl QuantMode { +impl std::string::ToString for QuantMode { fn to_string(&self) -> String { match *self { QuantMode::ELBG => "elbg".to_string(), @@ -243,6 +243,8 @@ struct CinepakEncoder { v4_cb: [YUVCode; 256], v1_cur_cb: [YUVCode; 256], v4_cur_cb: [YUVCode; 256], + v1_len: usize, + v4_len: usize, v1_idx: Vec, v4_idx: Vec, grayscale: bool, @@ -270,7 +272,7 @@ impl CinepakEncoder { pkt: None, lastfrm: None, frmcount: 0, - qmode: QuantMode::ELBG, + qmode: QuantMode::MedianCut, key_int: 25, quality: 0, nstrips: 2, @@ -280,6 +282,8 @@ impl CinepakEncoder { v4_cb: [YUVCode::default(); 256], v1_cur_cb: [YUVCode::default(); 256], v4_cur_cb: [YUVCode::default(); 256], + v1_len: 0, + v4_len: 0, grayscale: false, rng: RNG::new(), v1_idx: Vec::new(), @@ -339,7 +343,7 @@ impl CinepakEncoder { voff += vstride * 2; } } - fn find_nearest(codebook: &[YUVCode; 256], code: YUVCode) -> (u8, u32) { + fn find_nearest(codebook: &[YUVCode], code: YUVCode) -> (u8, u32) { let mut min_dist = std::u32::MAX; let mut idx = 0; for (i, cw) in codebook.iter().enumerate() { @@ -432,7 +436,7 @@ impl CinepakEncoder { for _ in (start..end).step_by(4) { for x in (0..width).step_by(4) { if cur_bit == 0 { - if !intra || self.v1_idx.len() > 0 { + if !intra || !self.v1_idx.is_empty() { cur_mask = *miter.next().unwrap(); } else { cur_mask = 0xFFFFFFFF; @@ -600,22 +604,33 @@ impl CinepakEncoder { QuantMode::ELBG => { let mut elbg_v1: ELBG = ELBG::new(&self.v1_cb); let mut elbg_v4: ELBG = ELBG::new(&self.v4_cb); - elbg_v1.quantise(&self.v1_entries, &mut self.v1_cur_cb); - elbg_v4.quantise(&self.v4_entries, &mut self.v4_cur_cb); + + for entry in self.v1_cb.iter_mut().skip(self.v1_len) { + self.rng.fill_entry(entry); + } + for entry in self.v4_cb.iter_mut().skip(self.v4_len) { + self.rng.fill_entry(entry); + } + + self.v1_len = elbg_v1.quantise(&self.v1_entries, &mut self.v1_cur_cb); + self.v4_len = elbg_v4.quantise(&self.v4_entries, &mut self.v4_cur_cb); }, QuantMode::Hybrid => { quantise_median_cut::(&self.v1_entries, &mut self.v1_cur_cb); quantise_median_cut::(&self.v4_entries, &mut self.v4_cur_cb); let mut elbg_v1: ELBG = ELBG::new(&self.v1_cur_cb); let mut elbg_v4: ELBG = ELBG::new(&self.v4_cur_cb); - elbg_v1.quantise(&self.v1_entries, &mut self.v1_cur_cb); - elbg_v4.quantise(&self.v4_entries, &mut self.v4_cur_cb); + self.v1_len = elbg_v1.quantise(&self.v1_entries, &mut self.v1_cur_cb); + self.v4_len = elbg_v4.quantise(&self.v4_entries, &mut self.v4_cur_cb); }, QuantMode::MedianCut => { - quantise_median_cut::(&self.v1_entries, &mut self.v1_cur_cb); - quantise_median_cut::(&self.v4_entries, &mut self.v4_cur_cb); + self.v1_len = quantise_median_cut::(&self.v1_entries, &mut self.v1_cur_cb); + self.v4_len = quantise_median_cut::(&self.v4_entries, &mut self.v4_cur_cb); }, }; + + for e in self.v1_cur_cb.iter_mut().skip(self.v1_len) { *e = YUVCode::default(); } + for e in self.v4_cur_cb.iter_mut().skip(self.v4_len) { *e = YUVCode::default(); } } fn encode_intra(&mut self, bw: &mut ByteWriter, in_frm: &NAVideoBuffer) -> EncoderResult { let (width, height) = in_frm.get_dimensions(0); @@ -660,16 +675,16 @@ impl CinepakEncoder { self.masks.reset(); for (v1_entry, v4_entries) in self.v1_entries.iter().zip(self.v4_entries.chunks(4)) { - let (v1_idx, v1_dist) = Self::find_nearest(&self.v1_cur_cb, *v1_entry); + let (v1_idx, v1_dist) = Self::find_nearest(&self.v1_cur_cb[..self.v1_len], *v1_entry); if v1_dist == 0 { self.masks.put_v1(); self.v1_idx.push(v1_idx); continue; } - let (v40_idx, v40_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[0]); - let (v41_idx, v41_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[1]); - let (v42_idx, v42_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[2]); - let (v43_idx, v43_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[3]); + let (v40_idx, v40_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[0]); + let (v41_idx, v41_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[1]); + let (v42_idx, v42_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[2]); + let (v43_idx, v43_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[3]); if v40_dist + v41_dist + v42_dist + v43_dist > v1_dist { self.masks.put_v4(); self.v4_idx.push(v40_idx); @@ -707,7 +722,7 @@ impl CinepakEncoder { self.render_stripe(true, start_line, end_line); - if self.v4_idx.len() == 0 { + if self.v4_idx.is_empty() { bw.write_byte(0x32)?; bw.write_u24be((self.v1_idx.len() + 4) as u32)?; bw.write_buf(self.v1_idx.as_slice())?; @@ -796,7 +811,7 @@ impl CinepakEncoder { self.masks.put_inter(true); continue; } - let (v1_idx, v1_dist) = Self::find_nearest(&self.v1_cur_cb, *v1_entry); + let (v1_idx, v1_dist) = Self::find_nearest(&self.v1_cur_cb[..self.v1_len], *v1_entry); if skip_dist < v1_dist { self.masks.put_inter(true); continue; @@ -808,10 +823,10 @@ impl CinepakEncoder { self.v1_idx.push(v1_idx); continue; } - let (v40_idx, v40_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[0]); - let (v41_idx, v41_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[1]); - let (v42_idx, v42_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[2]); - let (v43_idx, v43_dist) = Self::find_nearest(&self.v4_cur_cb, v4_entries[3]); + let (v40_idx, v40_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[0]); + let (v41_idx, v41_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[1]); + let (v42_idx, v42_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[2]); + let (v43_idx, v43_dist) = Self::find_nearest(&self.v4_cur_cb[..self.v4_len], v4_entries[3]); if v40_dist + v41_dist + v42_dist + v43_dist > v1_dist { self.masks.put_v4(); self.v4_idx.push(v40_idx); @@ -902,7 +917,7 @@ impl NAEncoder for CinepakEncoder { ofmt.format = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, true, YUV420_FORMAT)); Ok(ofmt) }, - NACodecTypeInfo::Audio(_) => return Err(EncoderError::FormatError), + NACodecTypeInfo::Audio(_) => Err(EncoderError::FormatError), NACodecTypeInfo::Video(vinfo) => { let pix_fmt = if vinfo.format == GRAY_FORMAT { GRAY_FORMAT } else { YUV420_FORMAT }; let outinfo = NAVideoInfo::new((vinfo.width + 3) & !3, (vinfo.height + 3) & !3, true, pix_fmt); @@ -928,7 +943,7 @@ impl NAEncoder for CinepakEncoder { } let out_info = NAVideoInfo::new(vinfo.width, vinfo.height, false, vinfo.format); - let info = NACodecInfo::new("cinepak", NACodecTypeInfo::Video(out_info.clone()), None); + let info = NACodecInfo::new("cinepak", NACodecTypeInfo::Video(out_info), None); let mut stream = NAStream::new(StreamType::Video, stream_id, info, encinfo.tb_num, encinfo.tb_den); stream.set_num(stream_id as usize); let stream = stream.into_ref(); @@ -1054,7 +1069,7 @@ mod test { let mut dmx_reg = RegisteredDemuxers::new(); generic_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - generic_register_all_codecs(&mut dec_reg); + generic_register_all_decoders(&mut dec_reg); let mut mux_reg = RegisteredMuxers::new(); generic_register_all_muxers(&mut mux_reg); let mut enc_reg = RegisteredEncoders::new();