From: Kostya Shishkov Date: Sun, 26 Dec 2021 16:15:39 +0000 (+0100) Subject: add nihav-misc crate and Aware MotionWavelets decoder in it X-Git-Url: https://git.nihav.org/?p=nihav.git;a=commitdiff_plain;h=549152963d868fc896287193b7ac7767e8794e01 add nihav-misc crate and Aware MotionWavelets decoder in it --- diff --git a/nihav-allstuff/Cargo.toml b/nihav-allstuff/Cargo.toml index 9fc23f7..33eea15 100644 --- a/nihav-allstuff/Cargo.toml +++ b/nihav-allstuff/Cargo.toml @@ -13,6 +13,7 @@ nihav_game = { path = "../nihav-game" } nihav_indeo = { path = "../nihav-indeo" } nihav_itu = { path = "../nihav-itu" } nihav_llaudio = { path = "../nihav-llaudio" } +nihav_misc = { path = "../nihav-misc" } nihav_mpeg = { path = "../nihav-mpeg" } nihav_ms = { path = "../nihav-ms" } nihav_qt = { path = "../nihav-qt" } diff --git a/nihav-allstuff/src/lib.rs b/nihav-allstuff/src/lib.rs index 233238a..7195640 100644 --- a/nihav-allstuff/src/lib.rs +++ b/nihav-allstuff/src/lib.rs @@ -26,6 +26,7 @@ use nihav_game::*; use nihav_indeo::indeo_register_all_decoders; use nihav_itu::itu_register_all_decoders; use nihav_llaudio::*; +use nihav_misc::*; use nihav_mpeg::*; use nihav_ms::*; use nihav_qt::qt_register_all_decoders; @@ -42,6 +43,7 @@ pub fn nihav_register_all_decoders(rd: &mut RegisteredDecoders) { indeo_register_all_decoders(rd); itu_register_all_decoders(rd); llaudio_register_all_decoders(rd); + misc_register_all_decoders(rd); mpeg_register_all_decoders(rd); ms_register_all_decoders(rd); qt_register_all_decoders(rd); diff --git a/nihav-misc/Cargo.toml b/nihav-misc/Cargo.toml new file mode 100644 index 0000000..faca21b --- /dev/null +++ b/nihav-misc/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "nihav_misc" +version = "0.1.0" +authors = ["Kostya Shishkov "] +edition = "2018" + +[dependencies.nihav_core] +path = "../nihav-core" + +[dependencies.nihav_codec_support] +path = "../nihav-codec-support" + +[dev-dependencies] +nihav_commonfmt = { path = "../nihav-commonfmt", default-features=false, features = ["all_demuxers"] } + +[features] +default = ["all_decoders"] +decoders = [] + +all_decoders = ["all_video_decoders", "all_audio_decoders"] + +all_video_decoders = ["decoder_mwv1"] +decoder_mwv1 = ["decoders"] + +all_audio_decoders = [] diff --git a/nihav-misc/src/codecs/mod.rs b/nihav-misc/src/codecs/mod.rs new file mode 100644 index 0000000..a41bd34 --- /dev/null +++ b/nihav-misc/src/codecs/mod.rs @@ -0,0 +1,21 @@ +use nihav_core::codecs::*; + +macro_rules! validate { + ($a:expr) => { if !$a { println!("check failed at {}:{}", file!(), line!()); return Err(DecoderError::InvalidData); } }; +} + +#[cfg(feature="decoder_mwv1")] +mod mwv1; + +const DECODERS: &[DecoderInfo] = &[ +#[cfg(feature="decoder_mwv1")] + DecoderInfo { name: "mwv1", get_decoder: mwv1::get_decoder }, +]; + +/// Registers all available codecs provided by this crate. +pub fn misc_register_all_decoders(rd: &mut RegisteredDecoders) { + for decoder in DECODERS.iter() { + rd.add_decoder(*decoder); + } +} + diff --git a/nihav-misc/src/codecs/mwv1.rs b/nihav-misc/src/codecs/mwv1.rs new file mode 100644 index 0000000..fd9b8b4 --- /dev/null +++ b/nihav-misc/src/codecs/mwv1.rs @@ -0,0 +1,649 @@ +use nihav_core::io::byteio::{ByteReader,MemoryReader}; +use nihav_core::io::bitreader::*; +use nihav_core::io::codebook::*; +use nihav_core::codecs::*; + +#[derive(Clone,Copy)] +struct BandPos { + plane: usize, + x: usize, + y: usize, + w: usize, + h: usize, + level: u8, + ilevel: u8, +} + +struct MWV1Decoder { + info: NACodecInfoRef, + mode: u32, + flags: u32, + l_cb: Codebook, + h_cb: Codebook, + bands: Vec, + tmp: Vec, + plane: [Vec; 3], + stride: [usize; 3], +} + +#[allow(clippy::too_many_arguments)] +fn decode_band(br: &mut BitReader, cb: &Codebook, dst: &mut [f32], w: usize, h: usize, stride: usize, scale: f32, round: bool, zero_skip: bool) -> DecoderResult<()> { + let mut ival = 0; + let mut zero_run = 0; + + for (y, row) in dst.chunks_mut(stride).take(h).enumerate() { + for i in 0..w { + let idx = if (y & 1) == 0 { i } else { w - 1 - i }; + if zero_run > 0 { + if !zero_skip { + row[idx] = (ival as f32) * scale; + } + zero_run -= 1; + continue; + } + let val = br.read_cb(cb)?; + let diff = match val { + 0 => { + let esc = br.read(8)? as i16 - 0x80; + if esc < 0 { + esc - 0x7B + } else { + esc + 0x7C + } + }, + 1 => { + let esc = br.read(12)? as i16 - 0x800; + if esc < 0 { + esc - 0xFB + } else { + esc + 0xFC + } + }, + 2 => { + zero_run = br.read(4)? + 4; + if zero_skip { + continue; + } + 0 + }, + 3 => { + zero_run = br.read(8)? + 20; + if zero_skip { + continue; + } + 0 + }, + 4 => { + zero_run = br.read(12)? + 276; + if zero_skip { + continue; + } + 0 + }, + 0x80 => { + let esc = (br.read(16)? ^ 0x8000) as i16; + if esc < 0 { + esc - 0x8FB + } else { + esc + 0x8FC + } + }, + 0xFC | 0xFD | 0xFE | 0xFF => { + zero_run = u32::from(val - 0xFC); + if zero_skip { + continue; + } + 0 + }, + _ => { + i16::from(val) - 0x80 + }, + }; + if !zero_skip { + ival += diff; + row[idx] = (ival as f32) * scale; + } else { + let bias = if !round { 0.0 } else if diff > 0 { 0.5 } else { -0.5 }; + row[idx] = ((diff as f32) + bias) * scale; + } + } + } + validate!(zero_run == 0); + + Ok(()) +} + +#[allow(clippy::too_many_arguments)] +fn decode_band2(br: &mut BitReader, cb: &Codebook, dst: &mut [f32], w: usize, h: usize, stride: usize, scale: f32, round: bool) -> DecoderResult<()> { + const ZERO_RUN_BITS: [u8; 12] = [ 16, 14, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]; + const ZERO_RUN_ADD: [u32; 12] = [ + 0x4839, 0x839, 0x439, 0x239, 0x139, 0xB9, 0x79, 0x59, 0x49, 0x41, 0x3D, 0x3B + ]; + + let mut zero_run = 0; + + for (y, row) in dst.chunks_mut(stride).take(h).enumerate() { + for i in 0..w { + let idx = if (y & 1) == 0 { i } else { w - 1 - i }; + + if zero_run > 0 { + zero_run -= 1; + continue; + } + let val = br.read_cb(cb)?; + let ival = match val { + 0x00..=0x40 => i16::from(val) - 32, + 0x41..=0x7B => { + zero_run = u32::from(val) - 0x41; + continue; + }, + 0xEF..=0xFA => { + let idx = (val - 0xEF) as usize; + zero_run = br.read(ZERO_RUN_BITS[idx])? + ZERO_RUN_ADD[idx]; + continue; + }, + 0xFE => { + let esc = br.read(14)? as i16 - 0x2000; + if esc < 0 { + esc - 0x220 + } else { + esc + 0x221 + } + }, + 0xFF => { + let esc = br.read(10)? as i16 - 0x200; + if esc < 0 { + esc - 0x20 + } else { + esc + 0x21 + } + }, + _ => return Err(DecoderError::InvalidData), + }; + let bias = if !round { 0.0 } else if ival > 0 { 0.5 } else { -0.5 }; + row[idx] = ((ival as f32) + bias) * scale; + } + } + validate!(zero_run == 0); + + Ok(()) +} + +fn combine_bands(lo: &[f32], hi: &[f32], dst: &mut [f32], step: usize, len: usize) { + dst[0] = (lo[0] - lo[step]) / 128.0 + (hi[0] + lo[0]) / 16.0; + dst[1] = (lo[step] - lo[0]) / 128.0 + (lo[0] - hi[0]) / 16.0; + let mut didx = 2; + let mut loidx = 0; + let mut hiidx = step; + for _i in 0..(((len + 1) >> 1) - 2) { + let tmp = (lo[loidx] - lo[loidx + 2 * step]) / 128.0; + dst[didx] = (lo[loidx + step] + hi[hiidx]) / 16.0 + tmp; + dst[didx + 1] = (lo[loidx + step] - hi[hiidx]) / 16.0 - tmp; + didx += 2; + loidx += step; + hiidx += step; + } + if (len & 1) == 0 { + let tmp = (lo[loidx] - lo[loidx + step]) / 128.0; + dst[didx] = (lo[loidx + step] + hi[hiidx]) / 16.0 + tmp; + dst[didx + 1] = (lo[loidx + step] - hi[hiidx]) / 16.0 - tmp; + } else { + dst[didx] = lo[loidx + step] / 16.0; + } +} + +fn map_index(idx: usize) -> u8 { idx as u8 } + +impl MWV1Decoder { + fn new() -> Self { + let mut cbr = TableCodebookDescReader::new(&L_CODE_BITS, &L_CODE_LENS, map_index); + let l_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + let mut cbr = TableCodebookDescReader::new(&H_CODE_BITS, &H_CODE_LENS, map_index); + let h_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap(); + MWV1Decoder { + info: NACodecInfo::new_dummy(), + l_cb, h_cb, + mode: 0, + flags: 0, + bands: Vec::new(), + plane: [Vec::new(), Vec::new(), Vec::new()], + stride: [0; 3], + tmp: Vec::new(), + } + } + fn reconstruct(&mut self, frm: &mut NASimpleVideoFrame) { + for band in self.bands.iter() { + if band.x == 0 || band.y == 0 { + continue; + } + + let stride = self.stride[band.plane] << band.ilevel; + let dst_yy = [0, 1 << band.ilevel >> 1]; + for &dst_y in dst_yy.iter() { + let dst = &mut self.plane[band.plane][dst_y * self.stride[band.plane]..]; + for row in dst.chunks_mut(stride).take(band.h) { + let (lo, hi) = row.split_at(band.x); + let size = band.x + band.w; + combine_bands(lo, hi, &mut self.tmp, 1, size); + row[..size].copy_from_slice(&self.tmp[..size]); + } + } + let size = band.y + band.h; + for x in 0..band.x + band.w { + let col = &self.plane[band.plane][x..]; + combine_bands(col, &col[stride/2..], &mut self.tmp, stride, size); + for y in 0..size { + self.plane[band.plane][x + y * (stride/2)] = self.tmp[y] * 128.0; + } + } + } + + for plane in 0..3 { + let dst = &mut frm.data[frm.offset[plane]..]; + for (drow, srow) in dst.chunks_mut(frm.stride[plane]).zip(self.plane[plane].chunks(self.stride[plane])) { + for (dst, &src) in drow.iter_mut().zip(srow.iter()) { + *dst = (src + 128.0).max(0.0).min(255.0) as u8; + } + } + } + } +} + +impl NADecoder for MWV1Decoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() { + if let Some(edata) = info.get_extradata() { + validate!(edata.len() >= 64); + let mut mr = MemoryReader::new_read(edata.as_slice()); + let mut br = ByteReader::new(&mut mr); + let len = br.read_u32be()? as usize; + validate!(edata.len() == len); + let _ = br.read_u32be()?; //always 7? + self.mode = br.read_u32be()?; //pic_fmt + let width = br.read_u32be()? as usize; + let height = br.read_u32be()? as usize; + let _smth = br.read_u16be()?; + let _bpp = br.read_u16be()?; + let _fmt = br.read_u32le()?; + let _unp_size = br.read_u32be()? as usize; + br.read_u32be()?; // always zero? + br.read_u32be()?; // always zero? + br.read_u32be()?; // always zero? + br.read_u32be()?; // always zero? + self.flags = br.read_u32be()?; // 0x100 - interlaced? + let mut levels = [[0; 2]; 3]; + for plane_lev in levels.iter_mut() { + for level in plane_lev.iter_mut() { + let lev = br.read_u16be()?; + validate!(lev < 32); + *level = lev as u8; + } + } + validate!(width > 1 && height > 1); + for plane_lev in levels.iter() { + if plane_lev[0] != plane_lev[1] { + return Err(DecoderError::NotImplemented); + } + } + let max_levels = levels[0][0].max(levels[1][0]).max(levels[2][0]); + validate!(max_levels < 8); + self.bands = Vec::with_capacity((max_levels as usize) * 9 + 1); + self.tmp = vec![0.0; width.max(height)]; + let mut dim = [[width, height], [width >> 1, height >> 1], [width >> 1, height >> 1]]; + + for level in (0..max_levels).rev() { + for plane in (0..3).rev() { + if level < levels[plane][0] { + let bp = BandPos { + plane, + level, + ilevel: levels[plane][0] - level, + x: (dim[plane][0] + 1) >> 1, + y: (dim[plane][1] + 1) >> 1, + w: dim[plane][0] >> 1, + h: dim[plane][1] >> 1, + }; + self.bands.push(bp); + } + } + for plane in (0..3).rev() { + if level < levels[plane][0] { + let bp = BandPos { + plane, + level, + ilevel: levels[plane][0] - level, + x: 0, + y: (dim[plane][1] + 1) >> 1, + w: (dim[plane][0] + 1) >> 1, + h: dim[plane][1] >> 1, + }; + self.bands.push(bp); + } + } + for plane in (0..3).rev() { + if level < levels[plane][0] { + let bp = BandPos { + plane, + level, + ilevel: levels[plane][0] - level, + x: (dim[plane][0] + 1) >> 1, + y: 0, + w: dim[plane][0] >> 1, + h: (dim[plane][1] + 1) >> 1, + }; + self.bands.push(bp); + } + } + + if level != 0 { + for plane in 0..3 { + if level < levels[plane][0] { + dim[plane][0] = (dim[plane][0] + 1) >> 1; + dim[plane][1] = (dim[plane][1] + 1) >> 1; + } + } + } + } + for plane in (0..3).rev() { + let bp = BandPos { + plane, + level: 0, + ilevel: levels[plane][0], + x: 0, + y: 0, + w: (dim[plane][0] + 1) >> 1, + h: (dim[plane][1] + 1) >> 1, + }; + self.bands.push(bp); + } + self.bands.reverse(); + + self.plane = [vec![0.0; width * height], vec![0.0; width * height / 4], vec![0.0; width * height / 4]]; + self.stride = [width, width >> 1, width >> 1]; + + let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(width, height, false, YUV420_FORMAT)); + self.info = NACodecInfo::new_ref(info.get_name(), myinfo, None).into_ref(); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let src = pkt.get_buffer(); + if src.len() <= 26 { return Err(DecoderError::ShortData); } + + let mut br = BitReader::new(&src, BitReaderMode::BE); + + for plane in self.plane.iter_mut() { + for el in plane.iter_mut() { + *el = 0.0; + } + } + + let mut has_hdr = false; + let mut band_iter = self.bands.iter_mut(); + + while br.left() > 5 { + let ff = br.read(32)?; + validate!(ff == 0xFFFFFFFF); + let tag_id = br.read(8)?; + match tag_id { + 0xAA => { + validate!(!has_hdr); + let size = br.read(32)?; + validate!(size >= 6); + let end = br.tell() + (size as usize) * 8 - 32; + br.read(16)?; + if (self.flags & 0x100) == 0 { + br.read(16)?; + br.read(16)?; + } + if self.mode > 1 { + br.read(8)?; + } + if self.mode > 4 { + let _size = br.read(32)?; + } + + validate!(br.tell() <= end); + let tail = end - br.tell(); + br.skip(tail as u32)?; + has_hdr = true; + }, + 0xAB => { + /*validate!(!has_hdr); + let size = br.read(32)?; + validate!(size >= 6); + br.read(16)?; + if self.levels == 2 || self.levels == 3 { + br.read(16)?; + br.read(16)?; + } + if components > 1 { + br.read(8)?; + } + br.skip((size - 6) * 8)?; + has_hdr = true;*/ + return Err(DecoderError::NotImplemented); + }, + 0xD1 => { + let next_band = band_iter.next(); + validate!(next_band.is_some()); + let band = *next_band.unwrap(); + + let scale; + let band_mode; + let lscale = (1 << band.level) as f32; + if self.mode < 3 { + /*let _ = br.read(32)?; + let _ = br.read(32)?; + scale = (br.read(32)? as f32) / 32768.0;*/ + return Err(DecoderError::NotImplemented); + } else { + band_mode = br.read(8)? as u8; + if band_mode == 0 { + scale = 0.0; + } else { + scale = (br.read(32)? as f32) * lscale / 32768.0; + } + } + + let dst_y = if band.y != 0 { 1 << band.ilevel >> 1 } else { 0 }; + + let dst = &mut self.plane[band.plane][band.x + dst_y * self.stride[band.plane]..]; + let stride = self.stride[band.plane] << band.ilevel; + let round = (band_mode & 8) != 0; + match band_mode { + 0 => {}, // empty band + 1 | 9 => { + decode_band(&mut br, &self.l_cb, dst, band.w, band.h, stride, scale, round, true)?; + }, + 2 | 10 => { + decode_band2(&mut br, &self.h_cb, dst, band.w, band.h, stride, scale, round)?; + }, + 5 => { + decode_band(&mut br, &self.l_cb, dst, band.w, band.h, stride, scale, false, false)?; + }, + _ => return Err(DecoderError::InvalidData), + }; + br.align(); + }, + 0xD2 | 0xDA => { + let size = br.read(32)?; + validate!(size >= 4); + br.skip((size - 4) * 8)?; + }, + 0xD7 => { + let size = br.read(32)?; + validate!(size == 13); + br.read(16)?; + for _ in 0..3 { + br.read(16)?; + } + br.read(8)?; + }, + 0xDD => { + return Err(DecoderError::NotImplemented); + }, + _ => { + return Err(DecoderError::NotImplemented); + }, + }; + if tag_id == 0 { break; } + } + + let vinfo = self.info.get_properties().get_video_info().unwrap(); + let bufinfo = alloc_video_buffer(vinfo, 2)?; + let mut buf = bufinfo.get_vbuf().unwrap(); + let mut frm = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap(); + + self.reconstruct(&mut frm); + + let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf)); + frm.set_keyframe(true); + frm.set_frame_type(FrameType::I); + Ok(frm.into_ref()) + } + fn flush(&mut self) { + } +} + +impl NAOptionHandler for MWV1Decoder { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub fn get_decoder() -> Box { + Box::new(MWV1Decoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::misc_register_all_decoders; + use nihav_commonfmt::generic_register_all_demuxers; + #[test] + fn test_mwv1() { + let mut dmx_reg = RegisteredDemuxers::new(); + generic_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + misc_register_all_decoders(&mut dec_reg); + // sample: https://samples.mplayerhq.hu/V-codecs/MWV1/test.avi + test_decoding("avi", "mwv1", "assets/Misc/mwv1.avi", Some(2), &dmx_reg, + &dec_reg, ExpectedTestResult::MD5Frames(vec![ + [0x9f2e0e5b, 0xa767c1ae, 0x8c009dca, 0x7159d0cd], + [0xfc00be21, 0x899736d0, 0x6b18dd40, 0x5261af2c], + [0xf113305d, 0xffac919f, 0x0b64890e, 0x18c60420]])); + } +} + +const L_CODE_BITS: [u16; 256] = [ + 0xFF6B, 0xFF76, 0x0014, 0x00F0, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, + 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, 0xFF80, 0xFF81, 0xFF82, + 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, + 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, 0xFF90, 0xFF91, 0xFF92, + 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, + 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, 0xFFA0, 0xFFA1, 0xFFA2, + 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9, 0xFFAA, + 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, 0xFFB0, 0xFFB1, 0xFFB2, + 0xFFB3, 0xFFB4, 0xFF6C, 0xFFB5, 0xFFB6, 0xFF6D, 0xFFB7, 0xFF6E, + 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFF6F, 0xFF5B, 0xFFBC, 0xFF4F, + 0xFFBD, 0xFF5C, 0xFFBE, 0xFFBF, 0xFF5D, 0xFF50, 0xFF5E, 0xFF70, + 0xFF5F, 0xFF60, 0xFF61, 0x1FDC, 0xFF51, 0x1FDD, 0x1FDE, 0x1FDF, + 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x0FE4, 0x0FE5, 0x07E8, 0x0FE6, + 0x0FE7, 0x07E9, 0x07EA, 0x07EB, 0x07EC, 0x07ED, 0x07EE, 0x03EA, + 0x03EB, 0x03EC, 0x01F0, 0x01F1, 0x01F2, 0x00F1, 0x00F2, 0x00F3, + 0x0074, 0x0075, 0x0034, 0x0035, 0x0015, 0x0016, 0x0008, 0x0000, + 0xFFC0, 0x0002, 0x0009, 0x0017, 0x0018, 0x0036, 0x0037, 0x0076, + 0x0077, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x01F3, 0x01F4, 0x03ED, + 0x03EE, 0x03EF, 0x03F0, 0x03F1, 0x03F2, 0x07EF, 0x07F0, 0x07F1, + 0x03F3, 0x0FE8, 0x0FE9, 0x0FEA, 0x0FEB, 0x0FEC, 0x0FED, 0x1FE4, + 0x1FE5, 0x1FE6, 0x1FE7, 0xFF52, 0x1FE8, 0x3FD2, 0xFF53, 0x7FA6, + 0xFF62, 0xFF63, 0xFF54, 0xFF55, 0xFF64, 0xFF65, 0xFF71, 0xFF72, + 0xFF56, 0xFF57, 0xFF58, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF73, + 0xFFC1, 0xFF74, 0xFFC2, 0xFF6A, 0xFF75, 0xFF59, 0xFF4E, 0xFF5A, + 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, 0xFFC8, 0xFFC9, 0xFFCA, + 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, 0xFFD0, 0xFFD1, 0xFFD2, + 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, 0xFFD8, 0xFFD9, 0xFFDA, + 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, 0xFFE0, 0xFFE1, 0xFFE2, + 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9, 0xFFEA, + 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, 0xFFF0, 0xFFF1, 0xFFF2, + 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, + 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0x0003, 0x0019, 0x0038, 0x0039 +]; +const L_CODE_LENS: [u8; 256] = [ + 16, 16, 5, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 13, 13, 13, + 13, 13, 13, 13, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 10, + 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 6, 6, 5, 5, 4, 2, + 16, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 10, + 10, 10, 10, 10, 10, 11, 11, 11, 10, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 16, 13, 14, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 3, 5, 6, 6 +]; +const H_CODE_BITS: [u16; 256] = [ + 0xFFFF, 0xFFE5, 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, + 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, 0xFFF0, 0xFFE0, 0xFFDB, 0xFFDC, + 0xFFDA, 0xFFD5, 0xFFD6, 0x1FF6, 0x1FF7, 0x0FEE, 0x0FEF, 0x07E0, + 0x07E1, 0x03E4, 0x01E4, 0x00E8, 0x006E, 0x0032, 0x0016, 0x0000, + 0x0000, 0x0001, 0x0017, 0x0033, 0x006F, 0x00E9, 0x01E5, 0x03E5, + 0x07E2, 0x07E3, 0x07E4, 0x0FF0, 0x1FF8, 0xFFD7, 0xFFD8, 0xFFD9, + 0xFFDD, 0xFFDE, 0xFFE1, 0xFFE2, 0xFFF1, 0xFFF2, 0xFFE3, 0xFFF3, + 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, + 0xFFFC, 0x0004, 0x000A, 0x0018, 0x0034, 0x0035, 0x0036, 0x0070, + 0x0071, 0x0072, 0x0073, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, + 0x00EF, 0x01E6, 0x01E7, 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, + 0x01ED, 0x01EE, 0x03E6, 0x03E7, 0x03E8, 0x03E9, 0x03EA, 0x03EB, + 0x03EC, 0x03ED, 0x03EE, 0x07E5, 0x07E6, 0x07E7, 0x07E8, 0x07E9, + 0x07EA, 0x07EB, 0x07EC, 0x07ED, 0x07EE, 0x07EF, 0x07F0, 0x07F1, + 0x07F2, 0x07F3, 0x07F4, 0x0FF1, 0x0FF2, 0x0FF3, 0x0FF4, 0x0FF5, + 0x0FF6, 0x0FF7, 0x0FF8, 0x0FF9, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFDF, + 0x1FF9, 0x3FF4, 0x0FFA, 0x07F5, 0x00F0, 0x00F1, 0x01EF, 0x01F0, + 0x01F1, 0x03EF, 0x07F6, 0x0000, 0x0000, 0xFFD4, 0xFFFD, 0xFFFE +]; +const H_CODE_LENS: [u8; 256] = [ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 13, 13, 12, 12, 11, 11, 10, 9, 8, 7, 6, 5, 2, + 0, 2, 5, 6, 7, 8, 9, 10, 11, 11, 11, 12, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 3, 4, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 13, 14, 12, 11, 8, 8, 9, 9, 9, 10, 11, 0, 0, 16, 16, 16 +]; diff --git a/nihav-misc/src/lib.rs b/nihav-misc/src/lib.rs new file mode 100644 index 0000000..9c5a754 --- /dev/null +++ b/nihav-misc/src/lib.rs @@ -0,0 +1,9 @@ +//! Crate for providing support for various formats that cannot be grouped elsewhere. +extern crate nihav_core; +extern crate nihav_codec_support; + +#[cfg(feature="decoders")] +mod codecs; + +#[cfg(feature="decoders")] +pub use crate::codecs::misc_register_all_decoders; diff --git a/nihav-registry/src/register.rs b/nihav-registry/src/register.rs index 6d36449..0e3cc64 100644 --- a/nihav-registry/src/register.rs +++ b/nihav-registry/src/register.rs @@ -284,6 +284,8 @@ static CODEC_REGISTER: &[CodecDescription] = &[ desc!(video-im; "jpeg", "JPEG"), desc!(video; "h264", "ITU H.264", CODEC_CAP_COMPLEX_REORDER | CODEC_CAP_HYBRID), + + desc!(video-im; "mwv1", "Aware MotionWavelets"), ]; static AVI_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[ @@ -329,6 +331,8 @@ static AVI_VIDEO_CODEC_REGISTER: &[(&[u8;4], &str)] = &[ (b"VP62", "vp6"), (b"VP6A", "vp6a"), (b"VP70", "vp7"), + + (b"MWV1", "mwv1"), ]; static WAV_CODEC_REGISTER: &[(u16, &str)] = &[