armovie: zero-terminated string is not exactly an error
[nihav.git] / nihav-llaudio / src / demuxers / flac.rs
1 use nihav_core::frame::*;
2 use nihav_core::demuxers::*;
3
4 #[derive(Clone,Copy,Default)]
5 struct FrameSeekInfo {
6 off: u64,
7 size: u64,
8 samplepos: u64,
9 sampleend: u64,
10 }
11
12 struct FLACDemuxer<'a> {
13 src: &'a mut ByteReader<'a>,
14 data_start: u64,
15 tot_samples: u64,
16 cur_samples: u64,
17 blk_samples: u16,
18 min_samples: u16,
19 min_size: usize,
20 max_size: usize,
21 srate: u32,
22 known_frames: Vec<FrameSeekInfo>,
23 build_index: bool,
24 frame_hdr: u32,
25 }
26
27 fn common_header_word(mut val: u32) -> u32 {
28 val &= !0x1F000; // blocking strategy and block size
29 let ch_map = (val >> 4) & 0xF;
30 if matches!(ch_map, 0x1 | 0x8 | 0x9 | 0xA) { // stereo coding modes
31 val &= !0xF0;
32 val |= 0x10;
33 }
34 val
35 }
36
37 impl<'a> FLACDemuxer<'a> {
38 fn new(io: &'a mut ByteReader<'a>) -> Self {
39 Self {
40 src: io,
41 data_start: 0,
42 tot_samples: 0,
43 cur_samples: 0,
44 blk_samples: 0,
45 min_samples: 0,
46 min_size: 0,
47 max_size: 0,
48 srate: 0,
49 known_frames: Vec::new(),
50 build_index: false,
51 frame_hdr: 0,
52 }
53 }
54 fn read_frame(&mut self) -> DemuxerResult<(Vec<u8>, u64, u64)> {
55 if self.src.is_eof() || (self.tot_samples != 0 && self.cur_samples == self.tot_samples) { return Err(DemuxerError::EOF); }
56 let mut buf = Vec::with_capacity(self.min_size);
57 let mut crc = 0;
58 let frame_start = self.src.tell();
59 for _ in 0..5 {
60 let byte = self.src.read_byte()?;
61 buf.push(byte);
62 crc = update_crc16(crc, byte);
63 }
64 if self.frame_hdr == 0 {
65 self.frame_hdr = read_u32be(&buf).unwrap_or(0);
66 }
67 let mut ref_crc = self.src.read_u16be()?;
68 loop {
69 let byte = self.src.read_byte()?;
70 let old_byte = (ref_crc >> 8) as u8;
71 buf.push(old_byte);
72 ref_crc = (ref_crc << 8) | u16::from(byte);
73 crc = update_crc16(crc, old_byte);
74 if buf.len() + 4 >= self.min_size && crc == ref_crc {
75 let ret = self.src.peek_u32be();
76 if ret.is_err() || (common_header_word(ret.unwrap_or(0)) == common_header_word(self.frame_hdr)) {
77 buf.push((ref_crc >> 8) as u8);
78 buf.push(ref_crc as u8);
79 break;
80 }
81 }
82 if (self.max_size > 0) && (buf.len() > self.max_size) {
83 return Err(DemuxerError::InvalidData);
84 }
85 if buf.len() > (1 << 23) {
86 return Err(DemuxerError::InvalidData);
87 }
88 }
89
90 let (duration, pts) = if self.blk_samples != 0 {
91 validate!((buf[1] & 1) == 0);
92 let blkno = u64::from(read_utf8(&buf[4..])?);
93 self.cur_samples = blkno * u64::from(self.blk_samples);
94 (u64::from(self.blk_samples), blkno)
95 } else {
96 let mut idx = 5;
97 while idx < buf.len() && (buf[idx] & 0x80) != 0 {
98 idx += 1;
99 }
100
101 let bsz_id = buf[2] >> 4;
102 let blksamps = match bsz_id {
103 0 => return Err(DemuxerError::InvalidData),
104 1 => 192,
105 2..=5 => 576 << (bsz_id - 2),
106 6 => {
107 validate!(idx < buf.len());
108 u64::from(buf[idx]) + 1
109 },
110 7 => {
111 validate!(idx + 2 <= buf.len());
112 u64::from(buf[idx]) * 256 + u64::from(buf[idx + 1]) + 1
113 },
114 _ => 256 << (bsz_id - 8),
115 };
116 let pts = u64::from(read_utf8(&buf[4..])?);
117
118 validate!(idx < buf.len());
119
120 (blksamps, pts)
121 };
122
123 let spos = if self.blk_samples != 0 { pts * u64::from(self.blk_samples) } else { pts };
124 if self.build_index && (self.known_frames.is_empty() || self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).samplepos < spos) {
125 let sampleend = spos + duration;
126 self.known_frames.push(FrameSeekInfo{off: frame_start, size: buf.len() as u64, samplepos: spos, sampleend });
127 }
128
129 self.cur_samples += duration;
130
131 Ok((buf, pts, duration))
132 }
133 }
134
135 fn update_crc16(crc: u16, byte: u8) -> u16 {
136 (crc << 8) ^ CRC16_TABLE[(((crc >> 8) as u8) ^ byte) as usize]
137 }
138
139 fn read_utf8(src: &[u8]) -> DemuxerResult<u32> {
140 if (src[0] & 0x80) == 0 {
141 return Ok(u32::from(src[0]));
142 }
143 let len = (!src[0]).leading_zeros() as usize;
144 validate!(len != 1 && len <= 5 && src.len() >= len);
145 let mut val = u32::from(src[0] & 0x1F);
146 for byte in src.iter().take(len).skip(1) {
147 validate!((*byte & 0xC0) == 0x80);
148 val = (val << 6) | u32::from(*byte & 0x3F);
149 }
150 Ok(val)
151 }
152
153 impl<'a> DemuxCore<'a> for FLACDemuxer<'a> {
154 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
155 let tag = self.src.read_tag()?;
156 validate!(&tag == b"fLaC");
157 let mut streaminfo: Vec<u8> = Vec::new();
158 let mut srate = 0u32;
159 let mut channels = 0u8;
160 loop {
161 let id1 = self.src.read_byte()?;
162 let len = self.src.read_u24be()? as usize;
163 let id = id1 & 0x7F;
164
165 match id {
166 0x00 => {
167 validate!(len >= 34);
168 streaminfo = vec![0u8; len];
169 self.src.read_buf(&mut streaminfo)?;
170 let min_bs = read_u16be(&streaminfo[0..])?;
171 let max_bs = read_u16be(&streaminfo[2..])?;
172 if min_bs == max_bs {
173 self.blk_samples = max_bs;
174 }
175 self.min_samples = min_bs;
176 self.min_size = read_u24be(&streaminfo[4..])? as usize;
177 self.max_size = read_u24be(&streaminfo[7..])? as usize;
178 let word = read_u24be(&streaminfo[10..])?;
179 srate = word >> 4;
180 channels = (((word >> 1) & 7) + 1) as u8;
181 self.tot_samples = (u64::from(streaminfo[13] & 0xF) << 32) | u64::from(read_u32be(&streaminfo[14..])?);
182 },
183 0x03 => {
184 validate!((len % 18) == 0);
185 seek_index.mode = SeekIndexMode::Present;
186 for _ in 0..len / 18 {
187 let sample = self.src.read_u64be()?;
188 let offset = self.src.read_u64be()?;
189 let _nsamps = self.src.read_u16be()?;
190 let time = sample * 1000 / u64::from(srate.max(1000));
191 seek_index.add_entry(0, SeekEntry { time, pts: sample, pos: offset });
192 }
193 },
194 _ => self.src.read_skip(len)?,
195 };
196
197 if (id1 & 0x80) != 0 {
198 break;
199 }
200 }
201 if seek_index.mode != SeekIndexMode::Present {
202 let min_size = if self.min_samples != 0 { self.min_samples } else { 2048 };
203 let nframes = self.tot_samples as usize / (min_size as usize);
204 self.known_frames = Vec::with_capacity(nframes.max(1));
205 seek_index.mode = SeekIndexMode::Automatic;
206 self.build_index = true;
207 } else {
208 self.build_index = false;
209 }
210 self.data_start = self.src.tell();
211 validate!(srate != 0);
212 self.srate = srate;
213
214 let base = if self.blk_samples != 0 { u32::from(self.blk_samples) } else { 1 };
215 let ahdr = NAAudioInfo::new(srate, channels, SND_S16P_FORMAT, base as usize);
216 let ainfo = NACodecInfo::new("flac", NACodecTypeInfo::Audio(ahdr), Some(streaminfo));
217 strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, base, srate, 0)).unwrap();
218
219 Ok(())
220 }
221 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
222 let (buf, pts, duration) = self.read_frame()?;
223
224 let stream = strmgr.get_stream(0).unwrap();
225 let ts = stream.make_ts(Some(pts), None, Some(duration));
226 let pkt = NAPacket::new(stream, ts, true, buf);
227
228 Ok(pkt)
229 }
230 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
231 if seek_index.mode == SeekIndexMode::Present {
232 let ret = seek_index.find_pos(time);
233 if ret.is_none() {
234 return Err(DemuxerError::SeekError);
235 }
236 let seek_info = ret.unwrap();
237 self.cur_samples = seek_info.pts;
238 self.src.seek(SeekFrom::Start(self.data_start + seek_info.pos))?;
239 Ok(())
240 } else if let NATimePoint::Milliseconds(ms) = time {
241 let samppos = NATimeInfo::time_to_ts(ms, 1000, 1, self.srate);
242 if self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).sampleend >= samppos {
243 for point in self.known_frames.iter().rev() {
244 if point.samplepos <= samppos {
245 self.src.seek(SeekFrom::Start(point.off))?;
246 self.cur_samples = point.samplepos;
247 return Ok(());
248 }
249 }
250 } else {
251 let startinfo = FrameSeekInfo { off: self.data_start, size: 0, samplepos: 0, sampleend: 0 };
252 let lentry = self.known_frames.last().unwrap_or(&startinfo);
253
254 self.src.seek(SeekFrom::Start(lentry.off + lentry.size))?;
255 self.cur_samples = lentry.sampleend;
256 loop {
257 let frame_start = self.src.tell();
258 let ret = self.read_frame();
259 if ret.is_err() {
260 return Err(DemuxerError::SeekError);
261 }
262 let (_, pts, duration) = ret.unwrap();
263 self.cur_samples = pts;
264 if self.blk_samples != 0 {
265 self.cur_samples *= u64::from(self.blk_samples);
266 }
267 if self.cur_samples <= samppos && self.cur_samples + duration >= samppos {
268 self.src.seek(SeekFrom::Start(frame_start))?;
269 return Ok(());
270 }
271 }
272 }
273 Err(DemuxerError::SeekError)
274 } else {
275 Err(DemuxerError::NotPossible)
276 }
277 }
278 fn get_duration(&self) -> u64 { self.tot_samples * 1000 / u64::from(self.srate) }
279 }
280
281 impl<'a> NAOptionHandler for FLACDemuxer<'a> {
282 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
283 fn set_options(&mut self, _options: &[NAOption]) { }
284 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
285 }
286
287 pub struct FLACDemuxerCreator { }
288
289 impl DemuxerCreator for FLACDemuxerCreator {
290 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
291 Box::new(FLACDemuxer::new(br))
292 }
293 fn get_name(&self) -> &'static str { "flac" }
294 }
295
296 #[cfg(test)]
297 mod test {
298 use super::*;
299 use std::fs::File;
300
301 #[test]
302 fn test_flac_demux() {
303 // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.flac
304 let mut file = File::open("assets/LLaudio/luckynight.flac").unwrap();
305 let mut fr = FileReader::new_read(&mut file);
306 let mut br = ByteReader::new(&mut fr);
307 let mut dmx = FLACDemuxer::new(&mut br);
308 let mut sm = StreamManager::new();
309 let mut si = SeekIndex::new();
310 dmx.open(&mut sm, &mut si).unwrap();
311 loop {
312 let pktres = dmx.get_frame(&mut sm);
313 if let Err(e) = pktres {
314 if (e as i32) == (DemuxerError::EOF as i32) { break; }
315 panic!("error");
316 }
317 let pkt = pktres.unwrap();
318 println!("Got {}", pkt);
319 }
320 }
321 }
322
323 const CRC16_TABLE: [u16; 256] = [
324 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
325 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
326 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
327 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
328 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
329 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
330 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
331 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
332 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
333 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
334 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
335 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
336 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
337 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
338 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
339 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
340 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
341 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
342 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
343 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
344 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
345 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
346 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
347 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
348 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
349 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
350 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
351 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
352 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
353 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
354 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
355 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
356 ];