add LinePack decoder
[nihav.git] / nihav-game / src / demuxers / fst.rs
CommitLineData
8d91d85f
KS
1use nihav_core::frame::*;
2use nihav_core::demuxers::*;
3
4#[allow(dead_code)]
5struct FutureVisionVideoDemuxer<'a> {
6 src: &'a mut ByteReader<'a>,
7 cur_frame: usize,
8 apos: u64,
9 vsize: Vec<usize>,
10 asize: Vec<usize>,
11 a_id: Option<usize>,
12 v_id: Option<usize>,
13 vframe: bool,
14}
15
16impl<'a> DemuxCore<'a> for FutureVisionVideoDemuxer<'a> {
17 #[allow(unused_variables)]
18 fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
19 let src = &mut self.src;
20
21 let magic = src.read_tag()?;
22 validate!(&magic == b"2TSF");
23 let width = src.read_u32le()? as usize;
24 let height = src.read_u32le()? as usize;
25 validate!(width != 0 && height != 0);
26 let _flags = src.read_u32le()?;
27 let nframes = src.read_u32le()? as usize;
28 let fps = src.read_u32le()?;
29 let arate = src.read_u32le()?;
30 let abits = src.read_u32le()?;
31
32 let vhdr = NAVideoInfo::new(width, height, false, PAL8_FORMAT);
33 let vci = NACodecTypeInfo::Video(vhdr);
34 let vinfo = NACodecInfo::new("fst-video", vci, None);
35 self.v_id = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, fps, nframes as u64));
36 if arate != 0 {
37 validate!(abits == 8 || abits == 16);
38 let ahdr = NAAudioInfo::new(arate, 1, if abits == 16 { SND_S16_FORMAT } else { SND_U8_FORMAT }, 2);
39 let ainfo = NACodecInfo::new("pcm", NACodecTypeInfo::Audio(ahdr), None);
40 self.a_id = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, arate, 2));
41 }
42 self.vsize = Vec::with_capacity(nframes);
43 self.asize = Vec::with_capacity(nframes);
44 for _ in 0..nframes {
45 let vsize = src.read_u32le()? as usize;
46 let asize = src.read_u16le()? as usize;
47 self.vsize.push(vsize);
48 self.asize.push(asize);
49 }
50 self.vframe = true;
51 self.cur_frame = 0;
52 self.apos = 0;
53 Ok(())
54 }
55
56 #[allow(unused_variables)]
57 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
58 if self.cur_frame >= self.vsize.len() { return Err(DemuxerError::EOF); }
59 let (id, size, pts) = if self.vframe {
60 self.vframe = self.a_id.is_none();
61
62 (self.v_id.unwrap_or(0), self.vsize[self.cur_frame], self.cur_frame as u64)
63 } else {
64 self.vframe = true;
65 let apos = self.apos;
66 self.apos += (self.asize[self.cur_frame] as u64) * 2;
67
68 (self.a_id.unwrap_or(0), self.asize[self.cur_frame], apos)
69 };
70
71 if self.vframe {
72 self.cur_frame += 1;
73 }
74
817e4872
KS
75 let stream = strmgr.get_stream(id).unwrap();
76 let ts = stream.make_ts(Some(pts), None, None);
77 self.src.read_packet(stream, ts, true, size)
8d91d85f
KS
78 }
79
80 fn seek(&mut self, _time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> {
81 Err(DemuxerError::NotPossible)
82 }
83 fn get_duration(&self) -> u64 { 0 }
84}
85impl<'a> NAOptionHandler for FutureVisionVideoDemuxer<'a> {
86 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
87 fn set_options(&mut self, _options: &[NAOption]) { }
88 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
89}
90impl<'a> FutureVisionVideoDemuxer<'a> {
91 fn new(io: &'a mut ByteReader<'a>) -> Self {
92 FutureVisionVideoDemuxer {
93 src: io,
94 cur_frame: 0,
95 apos: 0,
96 vsize: Vec::new(),
97 asize: Vec::new(),
98 a_id: None,
99 v_id: None,
100 vframe: false,
101 }
102 }
103}
104
105pub struct FSTDemuxerCreator { }
106
107impl DemuxerCreator for FSTDemuxerCreator {
108 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
109 Box::new(FutureVisionVideoDemuxer::new(br))
110 }
111 fn get_name(&self) -> &'static str { "fst" }
112}
113
114#[allow(dead_code)]
115struct FutureVisionAudioDemuxer<'a> {
116 src: &'a mut ByteReader<'a>,
117 a_id: usize,
118 end: u64,
119 arate: u32,
120}
121
122impl<'a> DemuxCore<'a> for FutureVisionAudioDemuxer<'a> {
123 #[allow(unused_variables)]
124 fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
125 let src = &mut self.src;
126
127 let magic = src.read_tag()?;
128 validate!(&magic == b"FCMP");
129 let size = u64::from(src.read_u32le()?);
130 let arate = src.read_u32le()?;
131 validate!(arate != 0);
132 let abits = src.read_u16le()?;
133 validate!(abits == 8 || abits == 16);
134
135 let ahdr = NAAudioInfo::new(arate, 1, if abits == 16 { SND_S16_FORMAT } else { SND_U8_FORMAT }, 2);
136 let ainfo = NACodecInfo::new("fst-audio", NACodecTypeInfo::Audio(ahdr), None);
137 self.a_id = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, arate, 2)).unwrap();
138 self.end = self.src.tell() + size;
139 self.arate = arate;
140 Ok(())
141 }
142
143 #[allow(unused_variables)]
144 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
145 if self.src.tell() >= self.end { return Err(DemuxerError::EOF); }
146 let size = (self.end - self.src.tell()).min(0x2000) as usize;
147 let pts = (self.src.tell() - 14) * 2;
148
817e4872
KS
149 let stream = strmgr.get_stream(self.a_id).unwrap();
150 let ts = stream.make_ts(Some(pts), None, None);
151 self.src.read_packet(stream, ts, true, size)
8d91d85f
KS
152 }
153
154 fn seek(&mut self, _time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> {
155 Err(DemuxerError::NotPossible)
156 }
157 fn get_duration(&self) -> u64 { (self.end - 14) * 2000 / u64::from(self.arate) }
158}
159impl<'a> NAOptionHandler for FutureVisionAudioDemuxer<'a> {
160 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
161 fn set_options(&mut self, _options: &[NAOption]) { }
162 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
163}
164impl<'a> FutureVisionAudioDemuxer<'a> {
165 fn new(io: &'a mut ByteReader<'a>) -> Self {
166 FutureVisionAudioDemuxer {
167 src: io,
168 a_id: 0,
169 end: 0,
170 arate: 0,
171 }
172 }
173}
174
175pub struct FCMPDemuxerCreator { }
176
177impl DemuxerCreator for FCMPDemuxerCreator {
178 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
179 Box::new(FutureVisionAudioDemuxer::new(br))
180 }
181 fn get_name(&self) -> &'static str { "fcmp" }
182}
183
184#[cfg(test)]
185mod test {
186 use super::*;
187 use std::fs::File;
188
886cde48 189 // samples from the Harvester game
8d91d85f
KS
190 #[test]
191 fn test_fst_demux() {
192 let mut file = File::open("assets/Game/c007.fst").unwrap();
193 let mut fr = FileReader::new_read(&mut file);
194 let mut br = ByteReader::new(&mut fr);
195 let mut dmx = FutureVisionVideoDemuxer::new(&mut br);
196 let mut sm = StreamManager::new();
197 let mut si = SeekIndex::new();
198 dmx.open(&mut sm, &mut si).unwrap();
199 loop {
200 let pktres = dmx.get_frame(&mut sm);
201 if let Err(e) = pktres {
202 if (e as i32) == (DemuxerError::EOF as i32) { break; }
203 panic!("error");
204 }
205 let pkt = pktres.unwrap();
206 println!("Got {}", pkt);
207 }
208 }
209
210 #[test]
211 fn test_fcmp_demux() {
212 let mut file = File::open("assets/Game/anxiety.cmp").unwrap();
213 let mut fr = FileReader::new_read(&mut file);
214 let mut br = ByteReader::new(&mut fr);
215 let mut dmx = FutureVisionAudioDemuxer::new(&mut br);
216 let mut sm = StreamManager::new();
217 let mut si = SeekIndex::new();
218 dmx.open(&mut sm, &mut si).unwrap();
219 loop {
220 let pktres = dmx.get_frame(&mut sm);
221 if let Err(e) = pktres {
222 if (e as i32) == (DemuxerError::EOF as i32) { break; }
223 panic!("error");
224 }
225 let pkt = pktres.unwrap();
226 println!("Got {}", pkt);
227 }
228 }
229}