1 use nihav_core::frame::*;
2 use nihav_core::demuxers::*;
6 struct IMAXDemuxer<'a> {
7 src: &'a mut ByteReader<'a>,
16 impl<'a> DemuxCore<'a> for IMAXDemuxer<'a> {
17 #[allow(unused_variables)]
18 fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
19 let src = &mut self.src;
21 let magic = src.read_tag()?;
22 validate!(&magic == b"IMAX");
23 let nframes = u64::from(src.read_u32le()?);
24 let fps = u32::from(src.read_u16le()?);
25 let magic2 = src.read_u16le()?;
26 validate!(magic2 == 0x102);
27 let _zero = src.read_u16le()?;
28 let _max_vframe_size = src.read_u32le()?;
29 let _buffering_size = src.read_u32le()?;
31 let vhdr = NAVideoInfo::new(320, 160, false, PAL8_FORMAT);
32 let vci = NACodecTypeInfo::Video(vhdr);
33 let vinfo = NACodecInfo::new("fable-imax", vci, None);
34 self.v_id = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, fps, nframes)).unwrap();
35 let ahdr = NAAudioInfo::new(22050, 1, SND_U8_FORMAT, 2);
36 let ainfo = NACodecInfo::new("pcm", NACodecTypeInfo::Audio(ahdr), None);
37 self.a_id = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, 22050, 2)).unwrap();
43 #[allow(unused_variables)]
44 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
46 let fsize = self.src.read_u32le()? as usize;
47 let ftype = self.src.read_u32le()?;
51 let stream = strmgr.get_stream(self.v_id).unwrap();
52 let ts = stream.make_ts(Some(self.cur_frame), None, None);
54 let mut pkt = self.src.read_packet(stream, ts, true, fsize)?;
55 pkt.add_side_data(NASideData::Palette(self.pal_change, self.pal.clone()));
56 self.pal_change = false;
60 validate!(fsize == 768);
61 let mut pal = [0u8; 1024];
62 for chunk in pal.chunks_mut(4) {
63 let r = self.src.read_byte()?;
64 let g = self.src.read_byte()?;
65 let b = self.src.read_byte()?;
66 chunk[0] = (r << 2) | (r >> 4);
67 chunk[1] = (g << 2) | (g >> 4);
68 chunk[2] = (b << 2) | (b >> 4);
70 self.pal = Arc::new(pal);
71 self.pal_change = true;
74 let stream = strmgr.get_stream(self.a_id).unwrap();
75 let ts = stream.make_ts(Some(self.apos), None, None);
76 self.apos += fsize as u64;
77 return self.src.read_packet(stream, ts, true, fsize);
79 0xAAFF => return Err(DemuxerError::EOF),
80 _ => return Err(DemuxerError::InvalidData),
85 fn seek(&mut self, _time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> {
86 Err(DemuxerError::NotPossible)
88 fn get_duration(&self) -> u64 { 0 }
90 impl<'a> NAOptionHandler for IMAXDemuxer<'a> {
91 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
92 fn set_options(&mut self, _options: &[NAOption]) { }
93 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
95 impl<'a> IMAXDemuxer<'a> {
96 fn new(io: &'a mut ByteReader<'a>) -> Self {
103 pal: Arc::new([0; 1024]),
109 pub struct IMAXDemuxerCreator { }
111 impl DemuxerCreator for IMAXDemuxerCreator {
112 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
113 Box::new(IMAXDemuxer::new(br))
115 fn get_name(&self) -> &'static str { "fable-imax" }
124 fn test_imax_demux() {
125 // sample from Fable game
126 let mut file = File::open("assets/Game/present.imx").unwrap();
127 let mut fr = FileReader::new_read(&mut file);
128 let mut br = ByteReader::new(&mut fr);
129 let mut dmx = IMAXDemuxer::new(&mut br);
130 let mut sm = StreamManager::new();
131 let mut si = SeekIndex::new();
132 dmx.open(&mut sm, &mut si).unwrap();
134 let pktres = dmx.get_frame(&mut sm);
135 if let Err(e) = pktres {
136 if (e as i32) == (DemuxerError::EOF as i32) { break; }
139 let pkt = pktres.unwrap();
140 println!("Got {}", pkt);