From 66c43641769aa323a056a518c20eb8b678aad15d Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Tue, 4 Mar 2025 18:18:16 +0100 Subject: [PATCH] remove Beam SIFF formats support It has been moved to na_game_tool --- nihav-game/Cargo.toml | 7 +- nihav-game/src/codecs/beam.rs | 611 -------------------------------- nihav-game/src/codecs/mod.rs | 6 - nihav-game/src/demuxers/mod.rs | 5 - nihav-game/src/demuxers/siff.rs | 360 ------------------- nihav-registry/src/detect.rs | 10 - 6 files changed, 2 insertions(+), 997 deletions(-) delete mode 100644 nihav-game/src/codecs/beam.rs delete mode 100644 nihav-game/src/demuxers/siff.rs diff --git a/nihav-game/Cargo.toml b/nihav-game/Cargo.toml index ac34804..ab7da4b 100644 --- a/nihav-game/Cargo.toml +++ b/nihav-game/Cargo.toml @@ -18,7 +18,7 @@ nihav_commonfmt = { path = "../nihav-commonfmt", default-features=false, feature [features] default = ["all_decoders", "all_demuxers", "all_muxers"] demuxers = [] -all_demuxers = ["demuxer_bmv", "demuxer_bmv3", "demuxer_fcmp", "demuxer_fst", "demuxer_gdv", "demuxer_seq", "demuxer_sga", "demuxer_siff", "demuxer_smush", "demuxer_vmd"] +all_demuxers = ["demuxer_bmv", "demuxer_bmv3", "demuxer_fcmp", "demuxer_fst", "demuxer_gdv", "demuxer_seq", "demuxer_sga", "demuxer_smush", "demuxer_vmd"] demuxer_bmv = ["demuxers"] demuxer_bmv3 = ["demuxers"] demuxer_cnm = ["demuxers"] @@ -27,16 +27,13 @@ demuxer_fst = ["demuxers"] demuxer_gdv = ["demuxers"] demuxer_seq = ["demuxers"] demuxer_sga = ["demuxers"] -demuxer_siff = ["demuxers"] demuxer_smush = ["demuxers"] demuxer_vmd = ["demuxers"] all_decoders = ["all_video_decoders", "all_audio_decoders"] decoders = [] -all_video_decoders = ["decoder_beam_fcp", "decoder_beam_vbv", "decoder_bmv", "decoder_bmv3", "decoder_fstvid", "decoder_gdvvid", "decoder_ipma", "decoder_kmvc", "decoder_midivid", "decoder_midivid3", "decoder_seq", "decoder_sga", "decoder_smush_video", "decoder_vmd"] -decoder_beam_fcp = ["decoders"] -decoder_beam_vbv = ["decoders"] +all_video_decoders = ["decoder_bmv", "decoder_bmv3", "decoder_fstvid", "decoder_gdvvid", "decoder_ipma", "decoder_kmvc", "decoder_midivid", "decoder_midivid3", "decoder_seq", "decoder_sga", "decoder_smush_video", "decoder_vmd"] decoder_bmv = ["decoders"] decoder_bmv3 = ["decoders"] decoder_fstvid = ["decoders"] diff --git a/nihav-game/src/codecs/beam.rs b/nihav-game/src/codecs/beam.rs deleted file mode 100644 index e7d778f..0000000 --- a/nihav-game/src/codecs/beam.rs +++ /dev/null @@ -1,611 +0,0 @@ -use nihav_core::codecs::*; -use nihav_core::io::byteio::*; - -const VB_FLAG_GMC: u16 = 0x0001; -const VB_FLAG_AUDIO: u16 = 0x0004; -const VB_FLAG_VIDEO: u16 = 0x0008; -const VB_FLAG_PALETTE: u16 = 0x0010; - -const RGB555_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3, - comp_info: [ - Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 10, comp_offs: 0, next_elem: 2 }), - Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 5, comp_offs: 1, next_elem: 2 }), - Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 0, comp_offs: 2, next_elem: 2 }), - None, None], - elem_size: 2, be: false, alpha: false, palette: false }; - -fn check_size(x: usize, row_no: usize, dx: i16, dy: i16, stride: usize, len: usize) -> Option { - let start = (x as i32) + i32::from(dx) + ((row_no * 4) as i32 + i32::from(dy)) * (stride as i32); - if start >= 0 { - let start = start as usize; - let end = start + 4 + stride * 3; - - if end <= len { - Some(start) - } else { - None - } - } else { - None - } -} - -fn decode_video8(br: &mut ByteReader, dst: &mut [u8], prev_frame: &[u8], width: usize, gmv: [i16; 2]) -> DecoderResult { - let mut ftype = FrameType::I; - - let mut btc = 0; - let mut btypes = 0; - for (row_no, strip) in dst.chunks_mut(width * 4).enumerate() { - for x in (0..width).step_by(4) { - if btc == 0 { - btypes = br.read_byte()?; - btc = 4; - } - match btypes & 0xC0 { - 0xC0 => { - let t = br.read_byte()?; - let mut pattern = VB_PATTERNS[(t & 0x3F) as usize]; - let op = t >> 6; - validate!(op != 3); - if op == 0 { - let mut clr = [0; 2]; - br.read_buf(&mut clr)?; - for dline in strip[x..].chunks_mut(width).take(4) { - for el in dline[..4].iter_mut() { - *el = clr[(pattern & 1) as usize]; - pattern >>= 1; - } - } - } else { - if op == 2 { - pattern = !pattern; - } - let clr = br.read_byte()?; - - if let Some(start) = check_size(x, row_no, gmv[0], gmv[1], width, prev_frame.len()) { - for (dline, sline) in strip[x..].chunks_mut(width).zip(prev_frame[start..].chunks(width)).take(4) { - for (dst, &src) in dline[..4].iter_mut().zip(sline.iter()) { - *dst = if (pattern & 1) != 0 { clr } else { src }; - pattern >>= 1; - } - } - } else { - return Err(DecoderError::InvalidData); - } - - ftype = FrameType::P; - } - }, - 0x80 => { - let clr = br.read_byte()?; - for dline in strip[x..].chunks_mut(width).take(4) { - for el in dline[..4].iter_mut() { - *el = clr; - } - } - }, - 0x40 => { - let mv = br.read_byte()?; - if mv == 0 { - for dline in strip[x..].chunks_mut(width).take(4) { - br.read_buf(&mut dline[..4])?; - } - } else { - let mvx = (((mv & 0xF) ^ 8) as i16) - 8; - let mvy = (((mv >> 4) ^ 8) as i16) - 8; - if let Some(start) = check_size(x, row_no, gmv[0] + mvx, gmv[1] + mvy, width, prev_frame.len()) { - for (dline, sline) in strip[x..].chunks_mut(width).zip(prev_frame[start..].chunks(width)).take(4) { - dline[..4].copy_from_slice(&sline[..4]); - } - } else { - return Err(DecoderError::InvalidData); - } - ftype = FrameType::P; - } - }, - _ => { - if let Some(start) = check_size(x, row_no, gmv[0], gmv[1], width, prev_frame.len()) { - for (dline, sline) in strip[x..].chunks_mut(width).zip(prev_frame[start..].chunks(width)).take(4) { - dline[..4].copy_from_slice(&sline[..4]); - } - } else { - return Err(DecoderError::InvalidData); - } - ftype = FrameType::P; - }, - } - - btypes <<= 2; - btc -= 1; - } - } - - Ok(ftype) -} - -struct OldData { - pal: [u8; 768], - prev_frame: Vec, - cur_frame: Vec, - width: usize, - flags: u16, -} - -impl OldData { - fn new(w: usize, h: usize, flags: u16) -> Self { - Self { - pal: [0; 768], - prev_frame: vec![0; w * h], - cur_frame: vec![0; w * h], - width: w, - flags, - } - } - fn decode(&mut self, br: &mut ByteReader, vbuf: &mut NAVideoBufferRef) -> DecoderResult { - let asize = br.read_u16le()? as usize; - let _smth = br.read_u16le()? as usize; - let pal_size = br.read_u16le()? as usize; - if pal_size > 0 { - let pal_start = br.read_u16le()? as usize; - validate!(pal_start + pal_size <= 256); - br.read_buf(&mut self.pal[pal_start * 3..][..pal_size * 3])?; - } - br.read_skip(asize)?; - - let (gmv_x, gmv_y) = if (self.flags & 0x2000) != 0 { - let mvx = br.read_u16le()? as i16; - let mvy = br.read_u16le()? as i16; - (mvx, mvy) - } else { - (0, 0) - }; - - std::mem::swap(&mut self.cur_frame, &mut self.prev_frame); - - let ftype = decode_video8(br, &mut self.cur_frame, &self.prev_frame, self.width, [gmv_x, gmv_y])?; - - let stride = vbuf.get_stride(0); - let pal_off = vbuf.get_offset(1); - let data = vbuf.get_data_mut().unwrap(); - - for (dline, sline) in data.chunks_mut(stride).zip(self.cur_frame.chunks(self.width)) { - dline[..self.width].copy_from_slice(sline); - } - data[pal_off..][..768].copy_from_slice(&self.pal); - - Ok(ftype) - } -} - -struct Data8 { - pal: [u8; 768], - prev_frame: Vec, - cur_frame: Vec, - width: usize, -} - -impl Data8 { - fn new(w: usize, h: usize) -> Self { - Self { - pal: [0; 768], - prev_frame: vec![0; w * h], - cur_frame: vec![0; w * h], - width: w, - } - } - fn decode(&mut self, br: &mut ByteReader, vbuf: &mut NAVideoBufferRef) -> DecoderResult { - let flags = br.read_u16le()?; - let (gmv_x, gmv_y) = if (flags & VB_FLAG_GMC) != 0 { - let mvx = br.read_u16le()? as i16; - let mvy = br.read_u16le()? as i16; - (mvx, mvy) - } else { - (0, 0) - }; - if (flags & VB_FLAG_AUDIO) != 0 { - let asize = br.read_u32le()? as usize; - validate!(asize >= 4 && asize <= (br.left() as usize)); - br.read_skip(asize - 4)?; - } - let mut ftype = FrameType::Skip; - if (flags & VB_FLAG_VIDEO) != 0 { - std::mem::swap(&mut self.cur_frame, &mut self.prev_frame); - - let vsize = br.read_u32le()? as u64; - validate!(vsize > 4); - let end = br.tell() + vsize - 4; - - ftype = decode_video8(br, &mut self.cur_frame, &self.prev_frame, self.width, [gmv_x, gmv_y])?; - - validate!(br.tell() == end); - } - if (flags & VB_FLAG_PALETTE) != 0 { - let pal_size = br.read_u32le()? as usize; - validate!(pal_size > 6); - validate!(br.left() as usize >= pal_size - 4); - let start = br.read_byte()? as usize; - let mut size = br.read_byte()? as usize; - if size == 0 { - size = 256; - } - validate!(start + size <= 256); - validate!(size * 3 + 6 == pal_size); - br.read_buf(&mut self.pal[start * 3..][..size * 3])?; - } - - let stride = vbuf.get_stride(0); - let pal_off = vbuf.get_offset(1); - let data = vbuf.get_data_mut().unwrap(); - - for (dline, sline) in data.chunks_mut(stride).zip(self.cur_frame.chunks(self.width)) { - dline[..self.width].copy_from_slice(sline); - } - data[pal_off..][..768].copy_from_slice(&self.pal); - - Ok(ftype) - } -} - -struct Data16 { - prev_frame: Vec, - cur_frame: Vec, - pal: [u16; 256], - width: usize, -} - -impl Data16 { - fn new(w: usize, h: usize) -> Self { - Self { - prev_frame: vec![0; w * h], - cur_frame: vec![0; w * h], - pal: [0; 256], - width: w, - } - } - fn decode(&mut self, br: &mut ByteReader, vbuf: &mut NAVideoBufferRef) -> DecoderResult { - let flags = br.read_u16le()?; - let (gmv_x, gmv_y) = if (flags & VB_FLAG_GMC) != 0 { - let mvx = br.read_u16le()? as i16; - let mvy = br.read_u16le()? as i16; - (mvx, mvy) - } else { - (0, 0) - }; - if (flags & VB_FLAG_AUDIO) != 0 { - let asize = br.read_u32le()? as usize; - validate!(asize <= (br.left() as usize)); - br.read_skip(asize - 4)?; - } - let mut ftype = FrameType::Skip; - if (flags & VB_FLAG_VIDEO) != 0 { - let vsize = br.read_u32le()? as u64; - validate!(vsize > 4); - let end = br.tell() + vsize - 4; - let has_pal = (flags & VB_FLAG_PALETTE) != 0; - if has_pal { - let cur_off = br.tell(); - br.seek(SeekFrom::Current((vsize - 4) as i64))?; - let psize = br.read_u32le()? as usize; - validate!(psize > 4 && psize <= 0x204 && (psize & 1) == 0); - for el in self.pal[..(psize - 4)/ 2].iter_mut() { - *el = br.read_u16le()?; - } - br.seek(SeekFrom::Start(cur_off))?; - } - - std::mem::swap(&mut self.cur_frame, &mut self.prev_frame); - - let mut btc = 0; - let mut btypes = 0; - ftype = FrameType::I; - for (row_no, strip) in self.cur_frame.chunks_mut(self.width * 4).enumerate() { - for x in (0..self.width).step_by(4) { - if btc == 0 { - btypes = br.read_byte()?; - btc = 4; - } - match btypes & 0xC0 { - 0xC0 => { - let t = br.read_byte()?; - let mut pattern = VB_PATTERNS[(t & 0x3F) as usize]; - let op = t >> 6; - validate!(op != 3); - if op == 0 { - let mut clr = [0; 2]; - if has_pal { - clr[0] = self.pal[br.read_byte()? as usize]; - clr[1] = self.pal[br.read_byte()? as usize]; - } else { - clr[0] = br.read_u16le()?; - clr[1] = br.read_u16le()?; - } - for dline in strip[x..].chunks_mut(self.width).take(4) { - for el in dline[..4].iter_mut() { - *el = clr[(pattern & 1) as usize]; - pattern >>= 1; - } - } - } else { - if op == 2 { - pattern = !pattern; - } - let clr = if has_pal { - self.pal[br.read_byte()? as usize] - } else { - br.read_u16le()? - }; - - if let Some(start) = check_size(x, row_no, gmv_x, gmv_y, self.width, self.prev_frame.len()) { - for (dline, sline) in strip[x..].chunks_mut(self.width).zip(self.prev_frame[start..].chunks(self.width)).take(4) { - for (dst, &src) in dline[..4].iter_mut().zip(sline.iter()) { - *dst = if (pattern & 1) != 0 { clr } else { src }; - pattern >>= 1; - } - } - } else { - return Err(DecoderError::InvalidData); - } - ftype = FrameType::P; - } - }, - 0x80 => { - let clr = if has_pal { - self.pal[br.read_byte()? as usize] - } else { - br.read_u16le()? - }; - for dline in strip[x..].chunks_mut(self.width).take(4) { - for el in dline[..4].iter_mut() { - *el = clr; - } - } - }, - 0x40 => { - let mv = br.read_byte()?; - if mv == 0 { - if has_pal { - for dline in strip[x..].chunks_mut(self.width).take(4) { - for el in dline[..4].iter_mut() { - *el = self.pal[br.read_byte()? as usize]; - } - } - } else { - for dline in strip[x..].chunks_mut(self.width).take(4) { - for el in dline[..4].iter_mut() { - *el = br.read_u16le()?; - } - } - } - } else { - let mvx = (((mv & 0xF) ^ 8) as i16) - 8; - let mvy = (((mv >> 4) ^ 8) as i16) - 8; - if let Some(start) = check_size(x, row_no, gmv_x + mvx, gmv_y + mvy, self.width, self.prev_frame.len()) { - for (dline, sline) in strip[x..].chunks_mut(self.width).zip(self.prev_frame[start..].chunks(self.width)).take(4) { - dline[..4].copy_from_slice(&sline[..4]); - } - } else { - return Err(DecoderError::InvalidData); - } - ftype = FrameType::P; - } - }, - _ => { - if let Some(start) = check_size(x, row_no, gmv_x, gmv_y, self.width, self.prev_frame.len()) { - for (dline, sline) in strip[x..].chunks_mut(self.width).zip(self.prev_frame[start..].chunks(self.width)).take(4) { - dline[..4].copy_from_slice(&sline[..4]); - } - } else { - return Err(DecoderError::InvalidData); - } - ftype = FrameType::P; - }, - } - - btypes <<= 2; - btc -= 1; - } - } - validate!(br.tell() == end); - } - if (flags & VB_FLAG_PALETTE) != 0 { - let psize = br.read_u32le()? as usize; - br.read_skip(psize - 4)?; - } - - let stride = vbuf.get_stride(0); - let data = vbuf.get_data_mut().unwrap(); - - for (dline, sline) in data.chunks_mut(stride).zip(self.cur_frame.chunks(self.width)) { - dline[..self.width].copy_from_slice(sline); - } - - Ok(ftype) - } -} - -enum FrameData { - Old(OldData), - Pal(Data8), - New(Data16), - None, -} - -struct BeamVideoDecoder { - info: NACodecInfoRef, - data: FrameData, - fcp: bool, -} - -impl BeamVideoDecoder { - fn new(fcp: bool) -> Self { - Self { - info: NACodecInfoRef::default(), - data: FrameData::None, - fcp, - } - } -} - -impl NADecoder for BeamVideoDecoder { - fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { - if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { - let width = vinfo.get_width(); - let height = vinfo.get_height(); - validate!((width & 3) == 0 && (height & 3) == 0); - let fmt = match vinfo.bits { - _ if self.fcp => { - let edata = info.get_extradata(); - validate!(edata.is_some()); - let edata = edata.unwrap(); - validate!(edata.len() >= 2); - let flags = read_u16le(&edata)?; - self.data = FrameData::Old(OldData::new(width, height, flags)); - PAL8_FORMAT - }, - 8 => { - self.data = FrameData::Pal(Data8::new(width, height)); - PAL8_FORMAT - }, - 16 => { - self.data = FrameData::New(Data16::new(width, height)); - RGB555_FORMAT - }, - _ => return Err(DecoderError::InvalidData), - }; - - let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt)); - self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); - - Ok(()) - } else { - Err(DecoderError::InvalidData) - } - } - fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { - let src = pkt.get_buffer(); - validate!(src.len() > 1); - - let mut mr = MemoryReader::new_read(&src); - let mut br = ByteReader::new(&mut mr); - - let mut bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?; - - let ftype = match (&mut self.data, &mut bufinfo) { - (FrameData::Old(ref mut data), NABufferType::Video(ref mut vbuf)) => data.decode(&mut br, vbuf)?, - (FrameData::Pal(ref mut data), NABufferType::Video(ref mut vbuf)) => data.decode(&mut br, vbuf)?, - (FrameData::New(ref mut data), NABufferType::Video16(ref mut vbuf)) => data.decode(&mut br, vbuf)?, - _ => unreachable!(), - }; - - let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); - frm.set_keyframe(ftype == FrameType::I); - frm.set_frame_type(ftype); - Ok(frm.into_ref()) - } - fn flush(&mut self) { - } -} - -impl NAOptionHandler for BeamVideoDecoder { - 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_vbv() -> Box { - Box::new(BeamVideoDecoder::new(false)) -} - -pub fn get_decoder_fcp() -> Box { - Box::new(BeamVideoDecoder::new(true)) -} - -#[cfg(test)] -mod test { - use nihav_core::codecs::RegisteredDecoders; - use nihav_core::demuxers::RegisteredDemuxers; - use nihav_codec_support::test::dec_video::*; - use crate::game_register_all_decoders; - use crate::game_register_all_demuxers; - #[test] - fn test_beam_fcp() { - let mut dmx_reg = RegisteredDemuxers::new(); - game_register_all_demuxers(&mut dmx_reg); - let mut dec_reg = RegisteredDecoders::new(); - game_register_all_decoders(&mut dec_reg); - - // sample from The Dame was Loaded - test_decoding("siff", "beam-fcp", "assets/Game/siff/BEAM.FCP", Some(1000), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5Frames(vec![ - [0xa31342c0, 0x7afe5a76, 0x4111f17a, 0x30ec3a18], - [0xa31342c0, 0x7afe5a76, 0x4111f17a, 0x30ec3a18], - [0xa31342c0, 0x7afe5a76, 0x4111f17a, 0x30ec3a18], - [0xa31342c0, 0x7afe5a76, 0x4111f17a, 0x30ec3a18], - [0xa31342c0, 0x7afe5a76, 0x4111f17a, 0x30ec3a18], - [0x447870bf, 0x9bb22dab, 0x1f557dae, 0xc41575ad], - [0xeb3bd749, 0xc72811d3, 0x23d430b2, 0xc31dbd85], - [0x34bb16b4, 0x8e6066fe, 0xf3f6170a, 0xae4ec54e], - [0xee12f3ff, 0x4000ed43, 0x446336d7, 0x6cc344bf], - [0xfe6ba9e1, 0xcc97f503, 0xf6fc8f14, 0x40c334c0], - [0xb4229527, 0x8591ac0b, 0x1ba40ea8, 0x15aa5710]])); - } - #[test] - fn test_beam_video_8bit() { - let mut dmx_reg = RegisteredDemuxers::new(); - game_register_all_demuxers(&mut dmx_reg); - let mut dec_reg = RegisteredDecoders::new(); - game_register_all_decoders(&mut dec_reg); - - // sample from Lost Vikings 2 - test_decoding("siff", "beam-video", "assets/Game/siff/BEAM.VB", Some(1000), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5Frames(vec![ - [0x23604e03, 0x5781ea8a, 0x6b28d338, 0xc32d52d6], - [0xba68d1af, 0xacf630b7, 0x3899073d, 0x07135315], - [0xb10cd159, 0xd787a566, 0x523123ca, 0x8a757f9e], - [0x7f4dfb53, 0x581884ab, 0x71de61c0, 0xfec72a11], - [0xc2a40282, 0x729548e1, 0xc63211bf, 0x586158fc], - [0xb8bf753c, 0x53686fb2, 0x7d307625, 0xdab70698], - [0xa2e90475, 0x076ef58a, 0xe2276941, 0x9c47ca14], - [0x80f785df, 0x19e015ab, 0x93beaf9b, 0xff1d0907], - [0x957a9a60, 0xc8a8ae09, 0xad5ecf6c, 0x06097f03], - [0xdfd331d4, 0x2f6ba92b, 0x5bfcb6f8, 0x85bab2b9], - [0xf37d42c1, 0x7f54d6bd, 0xc2dca688, 0x60d64e8c], - [0x97a0e18b, 0xce9ea101, 0x56eea57c, 0xeb48e8b3], - [0x7043048c, 0x373fdf9d, 0x1b27d5b3, 0x3e4e9c7a]])); - } - #[test] - fn test_beam_video_16bit() { - let mut dmx_reg = RegisteredDemuxers::new(); - game_register_all_demuxers(&mut dmx_reg); - let mut dec_reg = RegisteredDecoders::new(); - game_register_all_decoders(&mut dec_reg); - - // sample from Alien Earth - test_decoding("siff", "beam-video", "assets/Game/siff/beamlogo.vbc", Some(500), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5Frames(vec![ - [0x90aeded9, 0x922cf894, 0x6ea78586, 0x35493724], - [0x90aeded9, 0x922cf894, 0x6ea78586, 0x35493724], - [0xa19daf5e, 0xa4858d72, 0x6700fc4d, 0x95c5e5dd], - [0x57d556af, 0x95c5c5f4, 0xe943f1e3, 0xb86941e1], - [0xa63351ae, 0x12ed21ee, 0x7246d1f4, 0xf3a5a79a], - [0x5930e388, 0x4891d37b, 0x619ea7ff, 0xc8dac16d], - [0x36eeaf75, 0x767e5e5e, 0x397e0100, 0xfa306811], - [0xb4722a6d, 0x61cc8483, 0xe4966f11, 0xa67cd0f4], - [0x62be7367, 0xcbeb77b2, 0xcb438480, 0xda39b47a], - [0x568b020d, 0x4992bc7f, 0xcbe20b5c, 0x697a35bc], - [0x35e5a6a8, 0x903c0d07, 0xbacf7734, 0xd1c54b6d], - [0xd3450588, 0xfae0a9ec, 0x72a8fce6, 0x7c57e3c1], - [0x90f0cc47, 0xd7e7d3ef, 0x46d81b4d, 0xf4495aa2]])); - } -} - -const VB_PATTERNS: [u16; 64] = [ - 0x0660, 0xFF00, 0xCCCC, 0xF000, 0x8888, 0x000F, 0x1111, 0xFEC8, - 0x8CEF, 0x137F, 0xF731, 0xC800, 0x008C, 0x0013, 0x3100, 0xCC00, - 0x00CC, 0x0033, 0x3300, 0x0FF0, 0x6666, 0x00F0, 0x0F00, 0x2222, - 0x4444, 0xF600, 0x8CC8, 0x006F, 0x1331, 0x318C, 0xC813, 0x33CC, - 0x6600, 0x0CC0, 0x0066, 0x0330, 0xF900, 0xC88C, 0x009F, 0x3113, - 0x6000, 0x0880, 0x0006, 0x0110, 0xCC88, 0xFC00, 0x00CF, 0x88CC, - 0x003F, 0x1133, 0x3311, 0xF300, 0x6FF6, 0x0603, 0x08C6, 0x8C63, - 0xC631, 0x6310, 0xC060, 0x0136, 0x136C, 0x36C8, 0x6C80, 0x324C -]; diff --git a/nihav-game/src/codecs/mod.rs b/nihav-game/src/codecs/mod.rs index 5923919..d2d3443 100644 --- a/nihav-game/src/codecs/mod.rs +++ b/nihav-game/src/codecs/mod.rs @@ -10,8 +10,6 @@ macro_rules! validate { ($a:expr) => { if !$a { return Err(DecoderError::InvalidData); } }; } -#[cfg(any(feature="decoder_beam_vbv",feature="decoder_beam_fcp"))] -pub mod beam; #[cfg(feature="decoder_bmv")] pub mod bmv; #[cfg(feature="decoder_bmv3")] @@ -45,10 +43,6 @@ const GAME_CODECS: &[DecoderInfo] = &[ DecoderInfo { name: "gdv-audio", get_decoder: gremlinvideo::get_decoder_audio }, #[cfg(feature="decoder_gdvvid")] DecoderInfo { name: "gdv-video", get_decoder: gremlinvideo::get_decoder_video }, -#[cfg(feature="decoder_beam_fcp")] - DecoderInfo { name: "beam-fcp", get_decoder: beam::get_decoder_fcp }, -#[cfg(feature="decoder_beam_vbv")] - DecoderInfo { name: "beam-video", get_decoder: beam::get_decoder_vbv }, #[cfg(feature="decoder_bmv")] DecoderInfo { name: "bmv-audio", get_decoder: bmv::get_decoder_audio }, #[cfg(feature="decoder_bmv")] diff --git a/nihav-game/src/demuxers/mod.rs b/nihav-game/src/demuxers/mod.rs index 1fa4cef..d08b487 100644 --- a/nihav-game/src/demuxers/mod.rs +++ b/nihav-game/src/demuxers/mod.rs @@ -20,9 +20,6 @@ mod gdv; mod seq; #[cfg(feature="demuxer_sga")] mod sga; -#[cfg(feature="demuxer_siff")] -#[allow(clippy::upper_case_acronyms)] -mod siff; #[cfg(feature="demuxer_smush")] mod smush; #[cfg(feature="demuxer_vmd")] @@ -43,8 +40,6 @@ const GAME_DEMUXERS: &[&dyn DemuxerCreator] = &[ &seq::SequenceDemuxerCreator {}, #[cfg(feature="demuxer_sga")] &sga::SGADemuxerCreator {}, -#[cfg(feature="demuxer_siff")] - &siff::SIFFDemuxerCreator {}, #[cfg(feature="demuxer_smush")] &smush::SmushDemuxerCreator {}, #[cfg(feature="demuxer_smush")] diff --git a/nihav-game/src/demuxers/siff.rs b/nihav-game/src/demuxers/siff.rs deleted file mode 100644 index 1c961be..0000000 --- a/nihav-game/src/demuxers/siff.rs +++ /dev/null @@ -1,360 +0,0 @@ -use nihav_core::frame::*; -use nihav_core::demuxers::*; - -const DEFAULT_FCP_DELAY: u64 = 100; -const DEFAULT_VBV_DELAY: u64 = 80; - -#[derive(Clone,Copy,Debug,PartialEq)] -enum SIFFType { - None, - FCP, - VBV, - Sound, -} - -struct SIFFDemuxer<'a> { - src: &'a mut ByteReader<'a>, - subtype: SIFFType, - size: u32, - ablock: usize, - nframes: usize, - cframe: usize, - vpts: u64, - abuf: Vec, - apts: u64, - ver: u8, -} - -impl<'a> SIFFDemuxer<'a> { - fn new(io: &'a mut ByteReader<'a>) -> Self { - Self { - src: io, - subtype: SIFFType::None, - size: 0, - ablock: 0, - nframes: 0, - cframe: 0, - vpts: 0, - abuf: Vec::new(), - apts: 0, - ver: 0, - } - } - - fn parse_fcp_header(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> { - let tag = self.src.read_tag()?; - validate!(&tag == b"FCHD"); - let hdr_size = self.src.read_u32be()? as usize; - validate!(hdr_size >= 16); - let mut flags = vec![0; 2]; - self.src.read_buf(&mut flags)?; - let width = self.src.read_u16le()? as usize; - let height = self.src.read_u16le()? as usize; - validate!(width > 0 && height > 0); - self.nframes = self.src.read_u16le()? as usize; - self.src.read_skip(8)?; - self.src.read_skip(hdr_size - 16)?; - - let vhdr = NAVideoInfo::new(width, height, false, PAL8_FORMAT); - let vci = NACodecTypeInfo::Video(vhdr); - let vinfo = NACodecInfo::new("beam-fcp", vci, Some(flags)); - if strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, 1000, self.nframes as u64 * DEFAULT_FCP_DELAY)).is_none() { - return Err(DemuxerError::MemoryError); - } - - self.ablock = 1; - let srate = 22050; - let ahdr = NAAudioInfo::new(srate, 1, SND_U8_FORMAT, 1); - let ainfo = NACodecInfo::new("pcm", NACodecTypeInfo::Audio(ahdr), None); - if strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, srate, 0)).is_none() { - return Err(DemuxerError::MemoryError); - } - - self.vpts = 0; - self.apts = 0; - self.cframe = 0; - - Ok(()) - } - fn get_fcp_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { - if self.cframe >= self.nframes { - return Err(DemuxerError::EOF); - } - let size = self.src.read_u16le()? as usize; - validate!(size > 8); - let stream = strmgr.get_stream(0).unwrap(); - let ts = stream.make_ts(Some(self.vpts), None, None); - let kframe = self.vpts == 0; - self.cframe += 1; - let pkt = self.src.read_packet(stream, ts, kframe, size - 2)?; - let buf = pkt.get_buffer(); - - let mut mr = MemoryReader::new_read(buf.as_slice()); - let mut br = ByteReader::new(&mut mr); - let asize = br.read_u16le()? as usize; - let duration = br.read_u16le()? as u64; - validate!(asize < buf.len()); - if asize > 0 { - let nclrs = br.read_u16le()? as usize; - if nclrs > 0 { - br.read_skip(nclrs * 3 + 2)?; - } - self.abuf.resize(asize, 0); - br.read_buf(&mut self.abuf)?; - } - - if duration > 0 { - self.vpts += duration; - } else { - self.vpts += DEFAULT_FCP_DELAY; - } - - Ok(pkt) - } - - fn parse_vbv_header(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> { - let tag = self.src.read_tag()?; - validate!(&tag == b"VBHD"); - let hdr_size = self.src.read_u32be()? as usize; - validate!(hdr_size >= 32); - let version = self.src.read_u16le()?; - validate!(version == 1 || version == 2); - self.ver = version as u8; - let width = self.src.read_u16le()? as usize; - let height = self.src.read_u16le()? as usize; - validate!(width > 0 && height > 0); - self.src.read_skip(4)?; - self.nframes = self.src.read_u16le()? as usize; - let flags = self.src.read_u16le()?; - let bits = flags as u8; - let channels = if (flags & 0x100) != 0 { 2 } else { 1 }; - validate!(bits == 0 || bits >= 8); - let srate = self.src.read_u16le()? as u32; - self.ablock = (bits as usize) * (channels as usize) / 8; - self.src.read_skip(16)?; - self.src.read_skip(hdr_size - 32)?; - - let mut vhdr = NAVideoInfo::new(width, height, false, if version == 1 { PAL8_FORMAT } else { RGB565_FORMAT }); - vhdr.bits = version as u8 * 8; - let vci = NACodecTypeInfo::Video(vhdr); - let vinfo = NACodecInfo::new("beam-video", vci, None); - if strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, 1000, self.nframes as u64 * DEFAULT_VBV_DELAY)).is_none() { - return Err(DemuxerError::MemoryError); - } - - if srate > 0 && bits > 0 { - let ahdr = NAAudioInfo::new(srate, channels, if bits == 8 { SND_U8_FORMAT } else { SND_S16_FORMAT }, self.ablock); - let ainfo = NACodecInfo::new("pcm", NACodecTypeInfo::Audio(ahdr), None); - if strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, srate, 0)).is_none() { - return Err(DemuxerError::MemoryError); - } - } - - self.vpts = 0; - self.apts = 0; - self.cframe = 0; - - Ok(()) - } - fn get_vbv_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { - if self.cframe >= self.nframes { - return Err(DemuxerError::EOF); - } - let size = self.src.read_u32le()? as usize; - validate!(size > 6); - let stream = strmgr.get_stream(0).unwrap(); - let ts = stream.make_ts(Some(self.vpts), None, None); - let kframe = self.vpts == 0; - self.cframe += 1; - let pkt = self.src.read_packet(stream, ts, kframe, size - 4)?; - let buf = pkt.get_buffer(); - - let mut mr = MemoryReader::new_read(buf.as_slice()); - let mut br = ByteReader::new(&mut mr); - let flags = br.read_u16le()?; - if (flags & 0x01) != 0 { - br.read_skip(4)?; - } - if (flags & 0x04) != 0 { - let asize = br.read_u32le()? as usize; - validate!((asize > 4) && asize < (buf.len() - (br.tell() as usize))); - self.abuf.resize(asize - 4, 0); - br.read_buf(&mut self.abuf)?; - } - if (flags & 0x08) != 0 { - let vsize = br.read_u32le()? as usize; - validate!(vsize > 4); - br.read_skip(vsize - 4)?; - } - if (flags & 0x10) != 0 { - let psize = br.read_u32le()? as usize; - validate!(psize > 4); - br.read_skip(psize - 4)?; - } - let delay = if (flags & 0x20) != 0 { - br.read_u16le()? as u64 - } else { 0 }; - self.vpts += if delay > 0 { delay } else { DEFAULT_VBV_DELAY }; - - Ok(pkt) - } - - fn parse_snd_header(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> { - let tag = self.src.read_tag()?; - validate!(&tag == b"SHDR"); - let hdr_size = self.src.read_u32be()? as usize; - validate!(hdr_size >= 8); - let duration = self.src.read_u32le()? as u64; - let srate = self.src.read_u16le()? as u32; - let flags = self.src.read_u16le()?; - let bits = flags as u8; - validate!(bits >= 8); - let channels = if (flags & 0x100) != 0 { 2 } else { 1 }; - self.ablock = (bits as usize) * (channels as usize); - self.src.read_skip(hdr_size - 8)?; - - let fmt = match bits { - 8 => SND_U8_FORMAT, - 16 => SND_S16_FORMAT, - 12 => NASoniton::new(12, SONITON_FLAG_PACKED | SONITON_FLAG_SIGNED), - _ => return Err(DemuxerError::NotImplemented), - }; - let ahdr = NAAudioInfo::new(srate, channels, fmt, self.ablock); - let ainfo = NACodecInfo::new("pcm", NACodecTypeInfo::Audio(ahdr), None); - if strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, srate, duration)).is_none() { - return Err(DemuxerError::MemoryError); - } - - Ok(()) - } - fn get_snd_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { - if self.size == 0 { - return Err(DemuxerError::EOF); - } - let cur_size = self.size.min(1024 * (self.ablock as u32)); - - let stream = strmgr.get_stream(0).unwrap(); - let ts = stream.make_ts(None, None, None); - let pkt = self.src.read_packet(stream, ts, true, cur_size as usize)?; - self.size -= cur_size; - - Ok(pkt) - } -} - -impl<'a> DemuxCore<'a> for SIFFDemuxer<'a> { - fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> { - let magic = self.src.read_tag()?; - validate!(&magic == b"SIFF"); - self.size = self.src.read_u32be()?; - let tag = self.src.read_tag()?; - self.subtype = match &tag { - b"FCPK" => SIFFType::FCP, - b"VBV1" => SIFFType::VBV, - b"SOUN" => SIFFType::Sound, - _ => return Err(DemuxerError::NotImplemented), - }; - - match self.subtype { - SIFFType::FCP => self.parse_fcp_header(strmgr)?, - SIFFType::VBV => self.parse_vbv_header(strmgr)?, - SIFFType::Sound => self.parse_snd_header(strmgr)?, - _ => unreachable!(), - }; - - let tag = self.src.read_tag()?; - validate!(&tag == b"BODY"); - let body_size = self.src.read_u32be()?; - validate!(self.src.tell() + u64::from(body_size) <= u64::from(self.size) + 8); - self.size = body_size; - - Ok(()) - } - - fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { - if !self.abuf.is_empty() { - let mut buf = Vec::new(); - std::mem::swap(&mut buf, &mut self.abuf); - - if let Some(stream) = strmgr.get_stream(1) { - let ts = stream.make_ts(Some(self.apts), None, None); - self.apts += (buf.len() / self.ablock) as u64; - return Ok(NAPacket::new(stream, ts, true, buf)); - } - } - match self.subtype { - SIFFType::FCP => self.get_fcp_frame(strmgr), - SIFFType::VBV => self.get_vbv_frame(strmgr), - SIFFType::Sound => self.get_snd_frame(strmgr), - _ => unreachable!(), - } - } - - fn seek(&mut self, _time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> { - Err(DemuxerError::NotPossible) - } - fn get_duration(&self) -> u64 { 0 } -} - -impl<'a> NAOptionHandler for SIFFDemuxer<'a> { - fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } - fn set_options(&mut self, _options: &[NAOption]) { } - fn query_option_value(&self, _name: &str) -> Option { None } -} - -pub struct SIFFDemuxerCreator { } - -impl DemuxerCreator for SIFFDemuxerCreator { - fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { - Box::new(SIFFDemuxer::new(br)) - } - fn get_name(&self) -> &'static str { "siff" } -} - -#[cfg(test)] -mod test { - use super::*; - use std::fs::File; - - fn test_siff_demux(name: &str) { - let mut file = File::open(name).unwrap(); - let mut fr = FileReader::new_read(&mut file); - let mut br = ByteReader::new(&mut fr); - let mut dmx = SIFFDemuxer::new(&mut br); - let mut sm = StreamManager::new(); - let mut si = SeekIndex::new(); - dmx.open(&mut sm, &mut si).unwrap(); - loop { - let pktres = dmx.get_frame(&mut sm); - if let Err(e) = pktres { - if (e as i32) == (DemuxerError::EOF as i32) { break; } - panic!("error"); - } - let pkt = pktres.unwrap(); - println!("Got {}", pkt); - } - } - - #[test] - fn test_siff_demux_fcp() { - // sample from The Dame was Loaded game - test_siff_demux("assets/Game/siff/BEAM.FCP"); - } - #[test] - fn test_siff_demux_anim_8bit() { - // sample from Lost Vikings 2 game - test_siff_demux("assets/Game/siff/BEAM.VB"); - } - #[test] - fn test_siff_demux_anim_16bit() { - // sample from Alien Earth game - test_siff_demux("assets/Game/siff/beamlogo.vbc"); - } - #[test] - fn test_siff_demux_snd() { - // sample from The Dame was Loaded game - test_siff_demux("assets/Game/siff/01AFIRST.SON"); - // sample from Lost Vikings 2 game - test_siff_demux("assets/Game/siff/01THEME.SON"); - } -} diff --git a/nihav-registry/src/detect.rs b/nihav-registry/src/detect.rs index 4b18a9b..ba5bc89 100644 --- a/nihav-registry/src/detect.rs +++ b/nihav-registry/src/detect.rs @@ -300,16 +300,6 @@ const DETECTORS: &[DetectConditions] = &[ extensions: ".gdv", conditions: &[CheckItem{offs: 0, cond: &CC::Eq(Arg::U32LE(0x29111994))}], }, - DetectConditions { - demux_name: "siff", - extensions: ".vb,.vbc,.fcp,.son", - conditions: &[CheckItem{offs: 0, cond: &CC::Str(b"SIFF")}, - CheckItem{offs: 4, cond: &CC::Or( - &CC::Or( - &CC::Str(b"VBV1VBHD"), - &CC::Str(b"SOUNSHDR")), - &CC::Str(b"FCPKFCHD"))}], - }, DetectConditions { demux_name: "smush", extensions: ".san", -- 2.39.5