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