introduce stream and container duration
[nihav.git] / nihav-llaudio / src / demuxers / ape.rs
CommitLineData
87927c57
KS
1use nihav_core::frame::*;
2use nihav_core::demuxers::*;
3
4#[derive(Clone,Copy)]
5struct Frame {
6 off: u32,
7 size: u32,
8 bits_off: u8,
9}
10
11struct APEDemuxer<'a> {
12 src: &'a mut ByteReader<'a>,
13 cur_frame: usize,
14 frames: Vec<Frame>,
15 normal_blocks: u32,
16 last_blocks: u32,
17 truncated: bool,
18}
19
20impl<'a> APEDemuxer<'a> {
21 fn new(io: &'a mut ByteReader<'a>) -> Self {
22 Self {
23 src: io,
24 cur_frame: 0,
25 frames: Vec::new(),
26 normal_blocks: 0,
27 last_blocks: 0,
28 truncated: false,
29 }
30 }
31}
32
33impl<'a> DemuxCore<'a> for APEDemuxer<'a> {
34 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
35 let src = &mut self.src;
36
37 let tag = src.read_tag()?;
38 validate!(&tag == b"MAC ");
39 let version = src.read_u16le()?;
40 validate!(version >= 3800 && version <= 3990);
41
42 let seektab_len;
43 let _wavtail_len;
44 let compr_type;
45 let flags;
46 let blocksperframe;
47 let finalblocks;
48 let nframes;
49 let bits;
50 let channels;
51 let srate;
52 if version >= 3980 {
53 src.read_skip(2)?;
54 let descriptor_len = src.read_u32le()? as usize;
55 let header_len = src.read_u32le()? as usize;
56 validate!(header_len == 24);
57 seektab_len = src.read_u32le()? as usize;
58 let _wavheader_len = src.read_u32le()? as usize;
59 let _audio_len = src.read_u64le()?;
60 _wavtail_len = src.read_u32le()? as usize;
61 src.read_skip(16)?; // unpacked data MD5
62 if descriptor_len > 52 {
63 src.read_skip(descriptor_len - 52)?;
64 }
65
66 compr_type = src.read_u16le()?;
67 flags = src.read_u16le()?;
68 blocksperframe = src.read_u32le()?;
69 finalblocks = src.read_u32le()?;
70 nframes = src.read_u32le()? as usize;
71 bits = src.read_u16le()?;
72 channels = src.read_u16le()?;
73 srate = src.read_u32le()?;
74 } else {
75 compr_type = src.read_u16le()?;
76 flags = src.read_u16le()?;
77 channels = src.read_u16le()?;
78 srate = src.read_u32le()?;
79
80 let wavheader_len = src.read_u32le()? as usize;
81 _wavtail_len = src.read_u32le()? as usize;
82 nframes = src.read_u32le()? as usize;
83 finalblocks = src.read_u32le()?;
84 if (flags & 0x04) != 0 {
85 src.read_u32le()?; // peak level
86 }
87 if (flags & 0x10) != 0 {
88 seektab_len = src.read_u32le()? as usize * 4;
89 } else {
90 seektab_len = nframes * 4;
91 }
92
93 if (flags & 0x01) != 0 {
94 bits = 8;
95 } else if (flags & 0x08) != 0 {
96 bits = 24;
97 } else {
98 bits = 16;
99 }
100
101 blocksperframe = 9216 * if version >= 3950 {
102 32
103 } else if (version >= 3900) || ((version >= 3800) && (compr_type >= 4000)) {
104 8
105 } else {
106 1
107 };
108
109 if (flags & 0x20) == 0 {
110 src.read_skip(wavheader_len)?;
111 }
112 }
113 validate!(srate > 0);
114 validate!(channels > 0 && channels < 256);
115 validate!(bits > 0 && bits <= 32);
116 validate!(nframes > 0 && nframes < (1 << 28));
7b228074 117 validate!(seektab_len >= nframes * 4);
87927c57
KS
118
119 self.frames = Vec::with_capacity(nframes);
120 self.normal_blocks = blocksperframe;
121 self.last_blocks = finalblocks;
122
123 seek_index.mode = SeekIndexMode::Present;
124 let first_off = src.peek_u32le()?;
125 validate!(u64::from(first_off) >= src.tell() + ((nframes * 4) as u64));
126 let mut last_off = first_off - 1;
127 for i in 0..nframes {
128 let off = src.read_u32le()?;
129 validate!(off > last_off);
130 let diff = (off - first_off) & 3;
131 self.frames.push(Frame {
132 off: off - diff,
133 size: 0,
134 bits_off: (diff as u8) * 8,
135 });
136
137 last_off = off;
138
139 let time = (i as u64) * u64::from(blocksperframe) * 1000 / u64::from(srate);
140 seek_index.add_entry(0, SeekEntry { time, pts: i as u64, pos: i as u64 });
141 }
142 if version < 3810 {
143 for frame in self.frames.iter_mut() {
144 let bits = src.read_byte()?;
145 validate!(bits < 32);
146 frame.bits_off += bits;
147 }
148 }
149 src.seek(SeekFrom::End(0))?;
150 let fsize = src.tell();
151 validate!(fsize > u64::from(self.frames[0].off));
152 self.truncated = u64::from(self.frames[self.frames.len() - 1].off) >= fsize;
153 if self.truncated {
154 let mut valid_frames = self.frames.len();
155 for frame in self.frames.iter_mut().rev() {
156 if u64::from(frame.off) >= fsize {
157 valid_frames -= 1;
158 }
159 }
160 self.frames.truncate(valid_frames);
161 validate!(!self.frames.is_empty());
162 self.truncated = true;
163 }
164 let mut last_off = fsize as u32;
165 for frame in self.frames.iter_mut().rev() {
166 frame.size = last_off - frame.off;
167 last_off = frame.off + (if frame.bits_off > 0 { 4 } else { 0 });
168 }
169
170 let mut hdr = vec![0u8; 16];
171 write_u16le(&mut hdr[0..], version)?;
172 write_u16le(&mut hdr[2..], compr_type)?;
173 write_u16le(&mut hdr[4..], flags)?;
174 hdr[6] = channels as u8;
175 hdr[7] = bits as u8;
176 write_u32le(&mut hdr[8..], srate)?;
177 write_u32le(&mut hdr[12..], blocksperframe)?;
178
179 let ahdr = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, 1);
180 let ainfo = NACodecInfo::new("ape", NACodecTypeInfo::Audio(ahdr), Some(hdr));
a480a0de 181 strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, blocksperframe, srate, nframes as u64)).unwrap();
87927c57
KS
182
183 self.cur_frame = 0;
184
185 Ok(())
186 }
187 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
188 if self.cur_frame >= self.frames.len() {
189 return Err(DemuxerError::EOF);
190 }
191
192 let size = self.frames[self.cur_frame].size as usize;
193 let off = self.frames[self.cur_frame].off;
194 let bits = self.frames[self.cur_frame].bits_off;
195 let nblocks = if (self.cur_frame < self.frames.len() - 1) || self.truncated { self.normal_blocks } else { self.last_blocks };
196
197 self.src.seek(SeekFrom::Start(off.into()))?;
198
199 let mut buf = vec![0u8; size + 8];
200 write_u32le(&mut buf[0..], nblocks)?;
201 buf[4] = bits;
202 self.src.read_buf(&mut buf[8..])?;
203
204 let stream = strmgr.get_stream(0).unwrap();
205 let (tb_num, tb_den) = stream.get_timebase();
206 let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, tb_num, tb_den);
207 let pkt = NAPacket::new(stream, ts, true, buf);
208
209 self.cur_frame += 1;
210
211 Ok(pkt)
212 }
213 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
214 let ret = seek_index.find_pos(time);
215 if ret.is_none() {
216 return Err(DemuxerError::SeekError);
217 }
218 let seek_info = ret.unwrap();
219 self.cur_frame = seek_info.pts as usize;
220 if self.cur_frame >= self.frames.len() {
221 return Err(DemuxerError::SeekError);
222 }
223
224 Ok(())
225 }
a480a0de 226 fn get_duration(&self) -> u64 { 0 }
87927c57
KS
227}
228
229impl<'a> NAOptionHandler for APEDemuxer<'a> {
230 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
231 fn set_options(&mut self, _options: &[NAOption]) { }
232 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
233}
234
235pub struct APEDemuxerCreator { }
236
237impl DemuxerCreator for APEDemuxerCreator {
238 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
239 Box::new(APEDemuxer::new(br))
240 }
241 fn get_name(&self) -> &'static str { "ape" }
242}
243
244#[cfg(test)]
245mod test {
246 use super::*;
247 use std::fs::File;
248
249 #[test]
250 fn test_ape_demux() {
251 let mut file = File::open("assets/LLaudio/ape/luckynight.ape").unwrap();
252 let mut fr = FileReader::new_read(&mut file);
253 let mut br = ByteReader::new(&mut fr);
254 let mut dmx = APEDemuxer::new(&mut br);
255 let mut sm = StreamManager::new();
256 let mut si = SeekIndex::new();
257 dmx.open(&mut sm, &mut si).unwrap();
258 loop {
259 let pktres = dmx.get_frame(&mut sm);
260 if let Err(e) = pktres {
261 if (e as i32) == (DemuxerError::EOF as i32) { break; }
262 panic!("error");
263 }
264 let pkt = pktres.unwrap();
265 println!("Got {}", pkt);
266 }
267 }
268}