add LinePack decoder
[nihav.git] / nihav-llaudio / src / demuxers / flacraw.rs
1 use nihav_core::frame::*;
2 use nihav_core::demuxers::*;
3
4 struct FLACDemuxer<'a> {
5 src: &'a mut ByteReader<'a>,
6 data_start: u64,
7 tot_samples: u64,
8 cur_samples: u64,
9 blk_samples: u16,
10 min_samples: u16,
11 min_size: usize,
12 max_size: usize,
13 srate: u32,
14 build_index: bool,
15 }
16
17 impl<'a> FLACDemuxer<'a> {
18 fn new(io: &'a mut ByteReader<'a>) -> Self {
19 Self {
20 src: io,
21 data_start: 0,
22 tot_samples: 0,
23 cur_samples: 0,
24 blk_samples: 0,
25 min_samples: 0,
26 min_size: 0,
27 max_size: 0,
28 srate: 0,
29 build_index: false,
30 }
31 }
32 }
33
34 impl<'a> RawDemuxCore<'a> for FLACDemuxer<'a> {
35 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
36 let tag = self.src.read_tag()?;
37 validate!(&tag == b"fLaC");
38 let mut streaminfo: Vec<u8> = Vec::new();
39 let mut srate = 0u32;
40 let mut channels = 0u8;
41 loop {
42 let id1 = self.src.read_byte()?;
43 let len = self.src.read_u24be()? as usize;
44 let id = id1 & 0x7F;
45
46 match id {
47 0x00 => {
48 validate!(len >= 34);
49 streaminfo = vec![0u8; len];
50 self.src.read_buf(&mut streaminfo)?;
51 let min_bs = read_u16be(&streaminfo[0..])?;
52 let max_bs = read_u16be(&streaminfo[2..])?;
53 if min_bs == max_bs {
54 self.blk_samples = max_bs;
55 }
56 self.min_samples = min_bs;
57 self.min_size = read_u24be(&streaminfo[4..])? as usize;
58 self.max_size = read_u24be(&streaminfo[7..])? as usize;
59 let word = read_u24be(&streaminfo[10..])?;
60 srate = word >> 4;
61 channels = (((word >> 1) & 7) + 1) as u8;
62 self.tot_samples = (u64::from(streaminfo[13] & 0xF) << 32) | u64::from(read_u32be(&streaminfo[14..])?);
63 },
64 0x03 => {
65 validate!((len % 18) == 0);
66 seek_index.mode = SeekIndexMode::Present;
67 for _ in 0..len / 18 {
68 let sample = self.src.read_u64be()?;
69 let offset = self.src.read_u64be()?;
70 let _nsamps = self.src.read_u16be()?;
71 let time = sample * 1000 / u64::from(srate.max(1000));
72 seek_index.add_entry(0, SeekEntry { time, pts: sample, pos: offset });
73 }
74 },
75 _ => self.src.read_skip(len)?,
76 };
77
78 if (id1 & 0x80) != 0 {
79 break;
80 }
81 }
82 if seek_index.mode != SeekIndexMode::Present {
83 seek_index.mode = SeekIndexMode::Automatic;
84 self.build_index = true;
85 } else {
86 self.build_index = false;
87 }
88 self.data_start = self.src.tell();
89 validate!(srate != 0);
90 self.srate = srate;
91
92 let base = if self.blk_samples != 0 { u32::from(self.blk_samples) } else { 1 };
93 let ahdr = NAAudioInfo::new(srate, channels, SND_S16P_FORMAT, base as usize);
94 let ainfo = NACodecInfo::new("flac", NACodecTypeInfo::Audio(ahdr), Some(streaminfo));
95 strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, base, srate, 0)).unwrap();
96
97 Ok(())
98 }
99 fn get_data(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NARawData> {
100 let stream = strmgr.get_stream(0).unwrap();
101 let mut buf = vec![0; 8192];
102 let size = self.src.read_buf_some(&mut buf)?;
103 buf.truncate(size);
104 Ok(NARawData::new(stream, buf))
105 }
106 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
107 if seek_index.mode == SeekIndexMode::Present {
108 let ret = seek_index.find_pos(time);
109 if ret.is_none() {
110 return Err(DemuxerError::SeekError);
111 }
112 let seek_info = ret.unwrap();
113 self.cur_samples = seek_info.pts;
114 self.src.seek(SeekFrom::Start(self.data_start + seek_info.pos))?;
115 Ok(())
116 } else {
117 Err(DemuxerError::NotPossible)
118 }
119 }
120 fn get_duration(&self) -> u64 { self.tot_samples * 1000 / u64::from(self.srate) }
121 }
122
123 impl<'a> NAOptionHandler for FLACDemuxer<'a> {
124 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
125 fn set_options(&mut self, _options: &[NAOption]) { }
126 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
127 }
128
129 pub struct FLACDemuxerCreator { }
130
131 impl RawDemuxerCreator for FLACDemuxerCreator {
132 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn RawDemuxCore<'a> + 'a> {
133 Box::new(FLACDemuxer::new(br))
134 }
135 fn get_name(&self) -> &'static str { "flac" }
136 fn check_format(&self, br: &mut ByteReader) -> bool {
137 if br.seek(SeekFrom::Start(0)).is_err() {
138 return false;
139 }
140 matches!(br.read_tag(), Ok([b'f', b'L', b'a', b'C']))
141 }
142 }
143
144 #[cfg(test)]
145 mod test {
146 use nihav_core::codecs::*;
147 use super::*;
148 use crate::llaudio_register_all_packetisers;
149 use std::fs::File;
150
151 #[test]
152 fn test_flac_raw_demux() {
153 // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.flac
154 let mut file = File::open("assets/LLaudio/luckynight.flac").unwrap();
155 let mut fr = FileReader::new_read(&mut file);
156 let mut br = ByteReader::new(&mut fr);
157 let mut dmx = FLACDemuxer::new(&mut br);
158 let mut sm = StreamManager::new();
159 let mut si = SeekIndex::new();
160 dmx.open(&mut sm, &mut si).unwrap();
161 let stream = sm.get_stream(0).unwrap();
162 let mut pkt_reg = RegisteredPacketisers::new();
163 llaudio_register_all_packetisers(&mut pkt_reg);
164 let creator = pkt_reg.find_packetiser("flac").unwrap();
165 let mut pkts = (creator)();
166 let mut tot_size = 0;
167 while let Ok(pkt) = dmx.get_data(&mut sm) {
168 tot_size += pkt.get_buffer().len();
169 pkts.add_data(&pkt.get_buffer());
170 }
171 let mut tot_size2 = 0;
172 let mut npkts = 0;
173 while let Ok(Some(pkt)) = pkts.get_packet(stream.clone()) {
174 tot_size2 += pkt.get_buffer().len();
175 npkts += 1;
176 }
177 assert_eq!(npkts, 579);
178 assert_eq!(tot_size, tot_size2);
179 }
180 }