[features]
default = ["all_decoders", "all_demuxers", "all_muxers"]
demuxers = []
-all_demuxers = ["demuxer_bmv", "demuxer_bmv3", "demuxer_fcmp", "demuxer_fst", "demuxer_gdv", "demuxer_hl_fmv", "demuxer_imax", "demuxer_q", "demuxer_rbt", "demuxer_seq", "demuxer_sga", "demuxer_siff", "demuxer_smush", "demuxer_vmd", "demuxer_vx"]
+all_demuxers = ["demuxer_bmv", "demuxer_bmv3", "demuxer_fcmp", "demuxer_fst", "demuxer_gdv", "demuxer_imax", "demuxer_q", "demuxer_rbt", "demuxer_seq", "demuxer_sga", "demuxer_siff", "demuxer_smush", "demuxer_vmd", "demuxer_vx"]
demuxer_bmv = ["demuxers"]
demuxer_bmv3 = ["demuxers"]
demuxer_cnm = ["demuxers"]
demuxer_fcmp = ["demuxers"]
demuxer_fst = ["demuxers"]
demuxer_gdv = ["demuxers"]
-demuxer_hl_fmv = ["demuxers"]
demuxer_imax = ["demuxers"]
demuxer_q = ["demuxers"]
demuxer_rbt = ["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_hl_fmv", "decoder_imax", "decoder_ipma", "decoder_midivid", "decoder_midivid3", "decoder_q", "decoder_rbt", "decoder_seq", "decoder_sga", "decoder_smush_video", "decoder_vmd", "decoder_vx"]
+all_video_decoders = ["decoder_beam_fcp", "decoder_beam_vbv", "decoder_bmv", "decoder_bmv3", "decoder_fstvid", "decoder_gdvvid", "decoder_imax", "decoder_ipma", "decoder_midivid", "decoder_midivid3", "decoder_q", "decoder_rbt", "decoder_seq", "decoder_sga", "decoder_smush_video", "decoder_vmd", "decoder_vx"]
decoder_beam_fcp = ["decoders"]
decoder_beam_vbv = ["decoders"]
decoder_bmv = ["decoders"]
decoder_bmv3 = ["decoders"]
decoder_fstvid = ["decoders"]
decoder_gdvvid = ["decoders"]
-decoder_hl_fmv = ["decoders"]
decoder_imax = ["decoders"]
decoder_ipma = ["decoders"]
decoder_midivid = ["decoders"]
+++ /dev/null
-use nihav_core::codecs::*;
-use nihav_core::io::byteio::*;
-
-const FRAME_W: usize = 320;
-const FRAME_H: usize = 240;
-const HIST_SIZE: usize = 32768;
-
-struct Pattern {
- len: u8,
- pattern: [u8; 16],
-}
-
-struct HighlanderDecoder {
- info: NACodecInfoRef,
- hist: [u8; HIST_SIZE],
- tmp1: [u8; FRAME_W * FRAME_H],
- tmp2: [u8; FRAME_W * FRAME_H * 17 / 16],
-}
-
-fn unpack(src: &[u8], dst: &mut [u8], hist: &mut [u8; HIST_SIZE]) -> DecoderResult<usize> {
- let mut mr = MemoryReader::new_read(src);
- let mut br = ByteReader::new(&mut mr);
-
- let mut mw = MemoryWriter::new_write(dst);
- let mut bw = ByteWriter::new(&mut mw);
-
- *hist = [0; HIST_SIZE];
-
- let mut pprev = 0;
- let mut prev = 0;
- while br.left() > 0 {
- let mut flags = br.read_byte()?;
- for _ in 0..8 {
- let idx = (usize::from(pprev) << 7) ^ usize::from(prev);
- if (flags & 1) == 0 {
- if br.left() == 0 {
- break;
- }
- hist[idx] = br.read_byte()?;
- }
- let val = hist[idx];
- bw.write_byte(val)?;
-
- flags >>= 1;
- pprev = prev;
- prev = val;
- }
- }
-
- Ok(bw.tell() as usize)
-}
-
-fn paint_frame(dst: &mut [u8], stride: usize, src: &[u8]) -> DecoderResult<()> {
- let mut mr = MemoryReader::new_read(src);
- let mut br = ByteReader::new(&mut mr);
-
- let mut blk_offs = [0; 16];
- for (y, offs) in blk_offs.chunks_mut(4).enumerate() {
- offs[0] = stride * y;
- offs[1] = stride * y + 1;
- offs[2] = stride * y + 2;
- offs[3] = stride * y + 3;
- }
-
- for row in dst.chunks_mut(stride * 4).take(FRAME_H / 4) {
- for xoff in (0..FRAME_W).step_by(4) {
- let idx = br.read_byte()? as usize;
- validate!(idx < PAINT_MODE.len());
- let mode = &PAINT_MODE[idx];
- validate!(i64::from(mode.len) <= br.left());
-
- for (&blk_off, &idx) in blk_offs.iter().zip(mode.pattern.iter()) {
- if idx == 0xFF {
- row[xoff + blk_off] = br.read_byte()?;
- }
- }
- for (&blk_off, &idx) in blk_offs.iter().zip(mode.pattern.iter()) {
- if idx != 0xFF {
- row[xoff + blk_off] = row[xoff + blk_offs[idx as usize]];
- }
- }
- }
- }
- Ok(())
-}
-
-impl HighlanderDecoder {
- fn new() -> Self {
- Self {
- info: NACodecInfoRef::default(),
- hist: [0; HIST_SIZE],
- tmp1: [0; FRAME_W * FRAME_H],
- tmp2: [0; FRAME_W * FRAME_H * 17 / 16],
- }
- }
-}
-
-impl NADecoder for HighlanderDecoder {
- fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
- if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
- let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(FRAME_W, FRAME_H, false, PAL8_FORMAT));
- 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<NAFrameRef> {
- let src = pkt.get_buffer();
- validate!(src.len() > 4);
-
- let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?;
- let bufo = bufinfo.get_vbuf();
- let mut buf = bufo.unwrap();
- let paloff = buf.get_offset(1);
- let stride = buf.get_stride(0);
- let data = buf.get_data_mut().unwrap();
- let dst = data.as_mut_slice();
-
- validate!(src.len() > 4);
-
- let size = read_u32le(&src)? as usize;
- validate!(size <= src.len() - 4);
-
- let size2 = unpack(&src[4..][..size], &mut self.tmp1, &mut self.hist)?;
- let size3 = unpack(&self.tmp1[..size2], &mut self.tmp2, &mut self.hist)?;
- paint_frame(dst, stride, &self.tmp2[..size3])?;
-
- let dpal = &mut dst[paloff..][..768];
- for (dst, &src) in dpal.iter_mut().zip(DEFAULT_PAL.iter()) {
- *dst = (src << 2) | (src >> 4);
- }
-
- let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
- frm.set_keyframe(true);
- frm.set_frame_type(FrameType::I);
- Ok(frm.into_ref())
- }
- fn flush(&mut self) {
- }
-}
-
-impl NAOptionHandler for HighlanderDecoder {
- fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
- fn set_options(&mut self, _options: &[NAOption]) { }
- fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
-}
-
-
-pub fn get_decoder() -> Box<dyn NADecoder + Send> {
- Box::new(HighlanderDecoder::new())
-}
-
-#[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;
- // sample extracted from Highlander: The Last of the MacLeods unpublished game
- #[test]
- fn test_hl_fmv_video() {
- 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);
-
- test_decoding("hl-fmv", "hl-fmv-video", "assets/Game/0260.fmv", Some(10), &dmx_reg, &dec_reg,
- ExpectedTestResult::MD5([0x369659f0, 0x417ad3a7, 0xc62dfc6f, 0x6e5fe871]));
- }
-}
-
-const PAINT_MODE: [Pattern; 9] = [
- Pattern {
- len: 1,
- pattern: [
- 0xFF, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
- ],
- },
- Pattern {
- len: 2,
- pattern: [
- 0x05, 0x09, 0x05, 0x09,
- 0x09, 0xFF, 0x09, 0x05,
- 0x05, 0xFF, 0x05, 0x09,
- 0x09, 0x05, 0x09, 0x05
- ],
- },
- Pattern {
- len: 2,
- pattern: [
- 0xFF, 0xFF, 0x00, 0x01,
- 0x01, 0x01, 0x01, 0x01,
- 0x00, 0x01, 0x00, 0x01,
- 0x01, 0x01, 0x01, 0x01
- ]
- },
- Pattern {
- len: 2,
- pattern: [
- 0xFF, 0xFF, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00
- ],
- },
- Pattern {
- len: 2,
- pattern: [
- 0x0E, 0x0E, 0x0E, 0x0E,
- 0x0E, 0x0F, 0x0E, 0x0F,
- 0x0E, 0x0E, 0x0E, 0x0E,
- 0x0E, 0x0F, 0xFF, 0xFF
- ],
- },
- Pattern {
- len: 2,
- pattern: [
- 0x0F, 0x0F, 0x0F, 0x0F,
- 0x0E, 0x0F, 0x0E, 0x0F,
- 0x0F, 0x0F, 0x0F, 0x0F,
- 0x0E, 0x0F, 0xFF, 0xFF
- ],
- },
- Pattern {
- len: 5,
- pattern: [
- 0xFF, 0xFF, 0x00, 0xFF,
- 0x01, 0xFF, 0x01, 0xFF,
- 0x00, 0x01, 0x00, 0x03,
- 0x03, 0x07, 0x03, 0x07
- ],
- },
- Pattern {
- len: 8,
- pattern: [
- 0xFF, 0xFF, 0xFF, 0xFF,
- 0x01, 0x00, 0x03, 0x02,
- 0xFF, 0xFF, 0xFF, 0xFF,
- 0x09, 0x08, 0x0B, 0x0A
- ],
- },
- Pattern {
- len: 16,
- pattern: [
- 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF
- ],
- }
-];
-
-const DEFAULT_PAL: [u8; 768] = [
- 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20,
- 0x00, 0x20, 0x00,
- 0x00, 0x20, 0x20,
- 0x20, 0x00, 0x00,
- 0x20, 0x00, 0x20,
- 0x20, 0x20, 0x00,
- 0x30, 0x30, 0x30,
- 0x30, 0x37, 0x30,
- 0x3C, 0x32, 0x29,
- 0x01, 0x01, 0x01,
- 0x02, 0x02, 0x02,
- 0x03, 0x03, 0x03,
- 0x04, 0x04, 0x04,
- 0x05, 0x05, 0x05,
- 0x07, 0x07, 0x07,
- 0x08, 0x08, 0x08,
- 0x0A, 0x0A, 0x0A,
- 0x15, 0x15, 0x15,
- 0x13, 0x13, 0x13,
- 0x10, 0x10, 0x10,
- 0x0E, 0x0E, 0x0E,
- 0x20, 0x20, 0x20,
- 0x00, 0x00, 0x20,
- 0x00, 0x20, 0x00,
- 0x00, 0x20, 0x20,
- 0x20, 0x00, 0x00,
- 0x20, 0x00, 0x20,
- 0x20, 0x20, 0x00,
- 0x00, 0x00, 0x0C,
- 0x00, 0x00, 0x19,
- 0x00, 0x00, 0x26,
- 0x00, 0x00, 0x33,
- 0x00, 0x0C, 0x00,
- 0x00, 0x0C, 0x0C,
- 0x00, 0x0C, 0x19,
- 0x00, 0x0C, 0x26,
- 0x00, 0x0C, 0x33,
- 0x00, 0x0C, 0x3F,
- 0x00, 0x19, 0x00,
- 0x00, 0x19, 0x0C,
- 0x00, 0x19, 0x19,
- 0x00, 0x19, 0x26,
- 0x00, 0x19, 0x33,
- 0x00, 0x19, 0x3F,
- 0x00, 0x26, 0x00,
- 0x00, 0x26, 0x0C,
- 0x00, 0x26, 0x19,
- 0x00, 0x26, 0x26,
- 0x00, 0x26, 0x33,
- 0x00, 0x26, 0x3F,
- 0x00, 0x33, 0x00,
- 0x00, 0x33, 0x0C,
- 0x00, 0x33, 0x19,
- 0x00, 0x33, 0x26,
- 0x00, 0x33, 0x33,
- 0x00, 0x33, 0x3F,
- 0x00, 0x3F, 0x19,
- 0x00, 0x3F, 0x26,
- 0x00, 0x3F, 0x33,
- 0x0C, 0x00, 0x00,
- 0x0C, 0x00, 0x0C,
- 0x0C, 0x00, 0x19,
- 0x0C, 0x00, 0x26,
- 0x0C, 0x00, 0x33,
- 0x0C, 0x00, 0x3F,
- 0x0C, 0x0C, 0x00,
- 0x0C, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x19,
- 0x0C, 0x0C, 0x26,
- 0x0C, 0x0C, 0x33,
- 0x0C, 0x0C, 0x3F,
- 0x0C, 0x19, 0x00,
- 0x0C, 0x19, 0x0C,
- 0x0C, 0x19, 0x19,
- 0x0C, 0x19, 0x26,
- 0x0C, 0x19, 0x33,
- 0x0C, 0x19, 0x3F,
- 0x0C, 0x26, 0x00,
- 0x0C, 0x26, 0x0C,
- 0x0C, 0x26, 0x19,
- 0x0C, 0x26, 0x26,
- 0x0C, 0x26, 0x33,
- 0x0C, 0x26, 0x3F,
- 0x0C, 0x33, 0x00,
- 0x0C, 0x33, 0x0C,
- 0x0C, 0x33, 0x19,
- 0x0C, 0x33, 0x26,
- 0x0C, 0x33, 0x33,
- 0x0C, 0x33, 0x3F,
- 0x0C, 0x3F, 0x0C,
- 0x0C, 0x3F, 0x19,
- 0x0C, 0x3F, 0x26,
- 0x0C, 0x3F, 0x33,
- 0x0C, 0x3F, 0x3F,
- 0x19, 0x00, 0x00,
- 0x19, 0x00, 0x0C,
- 0x19, 0x00, 0x19,
- 0x19, 0x00, 0x26,
- 0x19, 0x00, 0x33,
- 0x19, 0x00, 0x3F,
- 0x19, 0x0C, 0x00,
- 0x19, 0x0C, 0x0C,
- 0x19, 0x0C, 0x19,
- 0x19, 0x0C, 0x26,
- 0x19, 0x0C, 0x33,
- 0x19, 0x0C, 0x3F,
- 0x19, 0x19, 0x00,
- 0x19, 0x19, 0x0C,
- 0x19, 0x19, 0x19,
- 0x19, 0x19, 0x26,
- 0x19, 0x19, 0x33,
- 0x19, 0x26, 0x00,
- 0x19, 0x26, 0x0C,
- 0x19, 0x26, 0x19,
- 0x19, 0x26, 0x26,
- 0x19, 0x26, 0x33,
- 0x19, 0x26, 0x3F,
- 0x19, 0x33, 0x00,
- 0x19, 0x33, 0x0C,
- 0x19, 0x33, 0x26,
- 0x19, 0x33, 0x33,
- 0x19, 0x33, 0x3F,
- 0x19, 0x3F, 0x00,
- 0x19, 0x3F, 0x0C,
- 0x19, 0x3F, 0x26,
- 0x19, 0x3F, 0x33,
- 0x33, 0x00, 0x3F,
- 0x3F, 0x00, 0x33,
- 0x26, 0x26, 0x00,
- 0x26, 0x0C, 0x26,
- 0x26, 0x00, 0x26,
- 0x26, 0x00, 0x33,
- 0x26, 0x00, 0x00,
- 0x26, 0x0C, 0x0C,
- 0x26, 0x00, 0x19,
- 0x26, 0x0C, 0x33,
- 0x26, 0x00, 0x3F,
- 0x26, 0x19, 0x00,
- 0x26, 0x19, 0x0C,
- 0x26, 0x0C, 0x19,
- 0x26, 0x19, 0x26,
- 0x26, 0x19, 0x33,
- 0x26, 0x0C, 0x3F,
- 0x26, 0x26, 0x0C,
- 0x26, 0x26, 0x19,
- 0x26, 0x26, 0x26,
- 0x26, 0x26, 0x33,
- 0x26, 0x26, 0x3F,
- 0x26, 0x33, 0x00,
- 0x26, 0x33, 0x0C,
- 0x19, 0x33, 0x19,
- 0x26, 0x33, 0x26,
- 0x26, 0x33, 0x33,
- 0x26, 0x33, 0x3F,
- 0x26, 0x3F, 0x00,
- 0x26, 0x3F, 0x0C,
- 0x26, 0x33, 0x19,
- 0x26, 0x3F, 0x26,
- 0x26, 0x3F, 0x33,
- 0x26, 0x3F, 0x3F,
- 0x33, 0x00, 0x00,
- 0x26, 0x00, 0x0C,
- 0x33, 0x00, 0x19,
- 0x33, 0x00, 0x26,
- 0x33, 0x00, 0x33,
- 0x26, 0x0C, 0x00,
- 0x33, 0x0C, 0x0C,
- 0x33, 0x0C, 0x19,
- 0x33, 0x0C, 0x26,
- 0x33, 0x0C, 0x33,
- 0x33, 0x0C, 0x3F,
- 0x33, 0x19, 0x00,
- 0x33, 0x19, 0x0C,
- 0x26, 0x19, 0x19,
- 0x33, 0x19, 0x26,
- 0x33, 0x19, 0x33,
- 0x26, 0x19, 0x3F,
- 0x33, 0x26, 0x00,
- 0x33, 0x26, 0x0C,
- 0x33, 0x26, 0x19,
- 0x33, 0x26, 0x26,
- 0x33, 0x26, 0x33,
- 0x33, 0x26, 0x3F,
- 0x33, 0x33, 0x00,
- 0x33, 0x33, 0x0C,
- 0x33, 0x33, 0x19,
- 0x33, 0x33, 0x26,
- 0x33, 0x33, 0x33,
- 0x33, 0x33, 0x3F,
- 0x33, 0x3F, 0x00,
- 0x33, 0x3F, 0x0C,
- 0x26, 0x3F, 0x19,
- 0x33, 0x3F, 0x26,
- 0x33, 0x3F, 0x33,
- 0x33, 0x3F, 0x3F,
- 0x33, 0x00, 0x0C,
- 0x3F, 0x00, 0x19,
- 0x3F, 0x00, 0x26,
- 0x33, 0x0C, 0x00,
- 0x3F, 0x0C, 0x0C,
- 0x3F, 0x0C, 0x19,
- 0x3F, 0x0C, 0x26,
- 0x3F, 0x0C, 0x33,
- 0x3F, 0x0C, 0x3F,
- 0x3F, 0x19, 0x00,
- 0x3F, 0x19, 0x0C,
- 0x33, 0x19, 0x19,
- 0x3F, 0x19, 0x26,
- 0x3F, 0x19, 0x33,
- 0x33, 0x19, 0x3F,
- 0x3F, 0x26, 0x00,
- 0x3F, 0x26, 0x0C,
- 0x3F, 0x26, 0x19,
- 0x3F, 0x26, 0x26,
- 0x3F, 0x26, 0x33,
- 0x3F, 0x26, 0x3F,
- 0x3F, 0x33, 0x00,
- 0x3F, 0x33, 0x0C,
- 0x3F, 0x33, 0x19,
- 0x3F, 0x33, 0x26,
- 0x3F, 0x33, 0x33,
- 0x3F, 0x33, 0x3F,
- 0x3F, 0x3F, 0x0C,
- 0x33, 0x3F, 0x19,
- 0x3F, 0x3F, 0x26,
- 0x3F, 0x3F, 0x33,
- 0x19, 0x19, 0x3F,
- 0x19, 0x3F, 0x19,
- 0x19, 0x3F, 0x3F,
- 0x3F, 0x19, 0x19,
- 0x3F, 0x19, 0x3F,
- 0x3F, 0x3F, 0x19,
- 0x30, 0x30, 0x30,
- 0x17, 0x17, 0x17,
- 0x1D, 0x1D, 0x1D,
- 0x21, 0x21, 0x21,
- 0x25, 0x25, 0x25,
- 0x32, 0x32, 0x32,
- 0x2C, 0x2C, 0x2C,
- 0x35, 0x35, 0x35,
- 0x37, 0x37, 0x37,
- 0x38, 0x38, 0x38,
- 0x3A, 0x3A, 0x3A,
- 0x3C, 0x3C, 0x3C,
- 0x3E, 0x3E, 0x3E,
- 0x3C, 0x3E, 0x3F,
- 0x29, 0x28, 0x28,
- 0x20, 0x20, 0x20,
- 0x00, 0x00, 0x3F,
- 0x00, 0x3F, 0x00,
- 0x00, 0x3F, 0x3F,
- 0x3F, 0x00, 0x00,
- 0x3F, 0x00, 0x3F,
- 0x3F, 0x3F, 0x00,
- 0x3F, 0x3F, 0x3F
-];
+++ /dev/null
-use nihav_core::frame::*;
-use nihav_core::demuxers::*;
-
-#[allow(dead_code)]
-struct HighlanderFMVDemuxer<'a> {
- src: &'a mut ByteReader<'a>,
- vpts: u64,
- apts: u64,
-}
-
-impl<'a> DemuxCore<'a> for HighlanderFMVDemuxer<'a> {
- #[allow(unused_variables)]
- fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
- let src = &mut self.src;
-
- let tag = src.read_tag()?;
- validate!(&tag == b"FMV*");
- let size = src.read_u32le()?;
- validate!(size == 0);
-
- let vhdr = NAVideoInfo::new(320, 240, false, PAL8_FORMAT);
- let vci = NACodecTypeInfo::Video(vhdr);
- let vinfo = NACodecInfo::new("hl-fmv-video", vci, None);
- if strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 2, 25, 0)).is_none() {
- return Err(DemuxerError::MemoryError);
- }
- let ahdr = NAAudioInfo::new(22050, 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, 22050, 0)).is_none() {
- return Err(DemuxerError::MemoryError);
- }
-
- self.apts = 0;
- self.vpts = 0;
- Ok(())
- }
-
- fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
- let tag = self.src.read_tag()?;
- let size = self.src.read_u32le()? as usize;
- match &tag {
- b"AUD1" => {
- let stream = strmgr.get_stream_by_id(1).unwrap();
- let ts = stream.make_ts(Some(self.apts), None, None);
- self.apts += size as u64;
- self.src.read_packet(stream, ts, true, size)
- },
- b"VID3" => {
- let stream = strmgr.get_stream_by_id(0).unwrap();
- let ts = stream.make_ts(Some(self.vpts), None, None);
- self.vpts += 1;
- self.src.read_packet(stream, ts, true, size)
- },
- b"END*" => Err(DemuxerError::EOF),
- _ => Err(DemuxerError::InvalidData),
- }
- }
-
- fn seek(&mut self, _time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> {
- Err(DemuxerError::NotPossible)
- }
- fn get_duration(&self) -> u64 { 0 }
-}
-impl<'a> NAOptionHandler for HighlanderFMVDemuxer<'a> {
- fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
- fn set_options(&mut self, _options: &[NAOption]) { }
- fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
-}
-impl<'a> HighlanderFMVDemuxer<'a> {
- fn new(io: &'a mut ByteReader<'a>) -> Self {
- HighlanderFMVDemuxer {
- src: io,
- vpts: 0,
- apts: 0,
- }
- }
-}
-
-pub struct HighlanderFMVDemuxerCreator { }
-
-impl DemuxerCreator for HighlanderFMVDemuxerCreator {
- fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
- Box::new(HighlanderFMVDemuxer::new(br))
- }
- fn get_name(&self) -> &'static str { "hl-fmv" }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use std::fs::File;
-
- // sample extracted from Highlander: The Last of the MacLeods unpublished game
- #[test]
- fn test_highlander_fmv_demux() {
- let mut file = File::open("assets/Game/0010.fmv").unwrap();
- let mut fr = FileReader::new_read(&mut file);
- let mut br = ByteReader::new(&mut fr);
- let mut dmx = HighlanderFMVDemuxer::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);
- }
- }
-}