+++ /dev/null
-use nihav_core::frame::*;
-use nihav_core::demuxers::*;
-use std::sync::Arc;
-
-#[allow(dead_code)]
-struct IMAXDemuxer<'a> {
- src: &'a mut ByteReader<'a>,
- cur_frame: u64,
- apos: u64,
- a_id: usize,
- v_id: usize,
- pal: Arc<[u8; 1024]>,
- pal_change: bool,
-}
-
-impl<'a> DemuxCore<'a> for IMAXDemuxer<'a> {
- #[allow(unused_variables)]
- fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
- let src = &mut self.src;
-
- let magic = src.read_tag()?;
- validate!(&magic == b"IMAX");
- let nframes = u64::from(src.read_u32le()?);
- let fps = u32::from(src.read_u16le()?);
- let magic2 = src.read_u16le()?;
- validate!(magic2 == 0x102);
- let _zero = src.read_u16le()?;
- let _max_vframe_size = src.read_u32le()?;
- let _buffering_size = src.read_u32le()?;
-
- let vhdr = NAVideoInfo::new(320, 160, false, PAL8_FORMAT);
- let vci = NACodecTypeInfo::Video(vhdr);
- let vinfo = NACodecInfo::new("fable-imax", vci, None);
- self.v_id = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, fps, nframes)).unwrap();
- let ahdr = NAAudioInfo::new(22050, 1, SND_U8_FORMAT, 2);
- let ainfo = NACodecInfo::new("pcm", NACodecTypeInfo::Audio(ahdr), None);
- self.a_id = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, 22050, 2)).unwrap();
- self.cur_frame = 0;
- self.apos = 0;
- Ok(())
- }
-
- #[allow(unused_variables)]
- fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
- loop {
- let fsize = self.src.read_u32le()? as usize;
- let ftype = self.src.read_u32le()?;
-
- match ftype {
- 0xAA97 => {
- let str = strmgr.get_stream(self.v_id).unwrap();
- let (tb_num, tb_den) = str.get_timebase();
- let ts = NATimeInfo::new(Some(self.cur_frame), None, None, tb_num, tb_den);
- self.cur_frame += 1;
- let mut pkt = self.src.read_packet(str, ts, true, fsize)?;
- pkt.add_side_data(NASideData::Palette(self.pal_change, self.pal.clone()));
- self.pal_change = false;
- return Ok(pkt);
- },
- 0xAA98 => {
- validate!(fsize == 768);
- let mut pal = [0u8; 1024];
- for chunk in pal.chunks_mut(4) {
- let r = self.src.read_byte()?;
- let g = self.src.read_byte()?;
- let b = self.src.read_byte()?;
- chunk[0] = (r << 2) | (r >> 4);
- chunk[1] = (g << 2) | (g >> 4);
- chunk[2] = (b << 2) | (b >> 4);
- }
- self.pal = Arc::new(pal);
- self.pal_change = true;
- },
- 0xAA99 => {
- let str = strmgr.get_stream(self.a_id).unwrap();
- let (tb_num, tb_den) = str.get_timebase();
- let ts = NATimeInfo::new(Some(self.apos), None, None, tb_num, tb_den);
- self.apos += fsize as u64;
- return self.src.read_packet(str, ts, true, fsize);
- },
- 0xAAFF => return Err(DemuxerError::EOF),
- _ => return 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 IMAXDemuxer<'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> IMAXDemuxer<'a> {
- fn new(io: &'a mut ByteReader<'a>) -> Self {
- IMAXDemuxer {
- src: io,
- cur_frame: 0,
- apos: 0,
- a_id: 0,
- v_id: 0,
- pal: Arc::new([0; 1024]),
- pal_change: false,
- }
- }
-}
-
-pub struct IMAXDemuxerCreator { }
-
-impl DemuxerCreator for IMAXDemuxerCreator {
- fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
- Box::new(IMAXDemuxer::new(br))
- }
- fn get_name(&self) -> &'static str { "fable-imax" }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use std::fs::File;
-
- #[test]
- fn test_imax_demux() {
- let mut file = File::open("assets/Game/present.imx").unwrap();
- let mut fr = FileReader::new_read(&mut file);
- let mut br = ByteReader::new(&mut fr);
- let mut dmx = IMAXDemuxer::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);
- }
- }
-}