fix some warnings (unneeded parentheses, missing dyn keyword)
[nihav.git] / nihav-commonfmt / src / demuxers / wav.rs
CommitLineData
283abfa6
KS
1use nihav_core::demuxers::*;
2use nihav_registry::register;
3use nihav_core::demuxers::DemuxerError::*;
4
5macro_rules! mktag {
6 ($a:expr, $b:expr, $c:expr, $d:expr) => {
61cab15b 7 (u32::from($a) << 24) | (u32::from($b) << 16) | (u32::from($c) << 8) | u32::from($d)
283abfa6
KS
8 };
9 ($arr:expr) => {
61cab15b 10 (u32::from($arr[0]) << 24) | (u32::from($arr[1]) << 16) | (u32::from($arr[2]) << 8) | u32::from($arr[3])
283abfa6
KS
11 };
12}
13
14struct WAVDemuxer<'a> {
15 src: &'a mut ByteReader<'a>,
16 data_pos: u64,
17 data_end: u64,
18 srate: u32,
19 block_size: usize,
20 is_pcm: bool,
21 avg_bytes: u32,
22}
23
24impl<'a> DemuxCore<'a> for WAVDemuxer<'a> {
25 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
26 let riff = self.src.read_u32be()?;
27 let riff_size = self.src.read_u32le()? as usize;
ac818eac 28 let riff_end = self.src.tell() + if riff_size > 0 { riff_size as u64 } else { u64::from(std::u32::MAX) };
283abfa6
KS
29 let wave = self.src.read_u32be()?;
30 validate!(riff == mktag!(b"RIFF"));
31 validate!(wave == mktag!(b"WAVE"));
32
33 seek_index.mode = SeekIndexMode::Automatic;
34
35 let mut fmt_parsed = false;
36 let mut _duration = 0;
37 while self.src.tell() < riff_end {
38 let ctype = self.src.read_tag()?;
39 let csize = self.src.read_u32le()? as usize;
40 match &ctype {
41 b"fmt " => {
42 validate!(!fmt_parsed);
43 self.parse_fmt(strmgr, csize)?;
44 fmt_parsed = true;
45 },
46 b"fact" => {
47 validate!(csize == 4);
48 _duration = self.src.read_u32le()? as usize;
49 },
50 b"data" => {
51 validate!(fmt_parsed);
52 self.data_pos = self.src.tell();
53 self.data_end = self.data_pos + (csize as u64);
54 return Ok(());
55 },
56 _ => {
57 self.src.read_skip(csize)?;
58 },
59 };
60 }
61 Err(DemuxerError::InvalidData)
62 }
63
64 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
65 if self.src.tell() >= self.data_end {
66 return Err(DemuxerError::EOF);
67 }
68 let str = strmgr.get_stream(0);
69 if str.is_none() { return Err(InvalidData); }
70 let stream = str.unwrap();
71 let ts = NATimeInfo::new(None, None, None, 1, self.srate);
72 if self.is_pcm {
73 let mut bsize = self.block_size;
74 while bsize < 256 {
75 bsize <<= 1;
76 }
77 let mut buf = vec![0; bsize];
78 let size = self.src.read_buf_some(buf.as_mut_slice())?;
79 buf.truncate(size);
80 Ok(NAPacket::new(stream, ts, true, buf))
81 } else {
82 self.src.read_packet(stream, ts, true, self.block_size)
83 }
84 }
85
24d99894 86 fn seek(&mut self, time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> {
283abfa6 87 if self.block_size != 0 && self.avg_bytes != 0 {
24d99894
KS
88 let seek_off = match time {
89 NATimePoint::Milliseconds(ms) => {
90 let seek_dst = u64::from(self.avg_bytes) * ms / 1000;
91 seek_dst / (self.block_size as u64) * (self.block_size as u64)
92 },
93 NATimePoint::PTS(pts) => (self.block_size as u64) * pts,
94 NATimePoint::None => return Ok(()),
95 };
283abfa6
KS
96 self.src.seek(SeekFrom::Start(self.data_pos + seek_off))?;
97 Ok(())
98 } else {
99 Err(DemuxerError::NotImplemented)
100 }
101 }
102}
103
787b8d03
KS
104impl<'a> NAOptionHandler for WAVDemuxer<'a> {
105 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
106 fn set_options(&mut self, _options: &[NAOption]) { }
107 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
108}
109
283abfa6
KS
110impl<'a> WAVDemuxer<'a> {
111 fn new(io: &'a mut ByteReader<'a>) -> Self {
112 WAVDemuxer {
113 src: io,
114 data_pos: 0,
115 data_end: 0,
116 srate: 0,
117 block_size: 0,
118 is_pcm: false,
119 avg_bytes: 0,
120 }
121 }
122 fn parse_fmt(&mut self, strmgr: &mut StreamManager, csize: usize) -> DemuxerResult<()> {
123 validate!(csize >= 14);
124 let format_tag = self.src.read_u16le()?;
125 let channels = self.src.read_u16le()?;
126 validate!(channels < 256);
127 let samples_per_sec = self.src.read_u32le()?;
128 let avg_bytes_per_sec = self.src.read_u32le()?;
129 let block_align = self.src.read_u16le()? as usize;
130 if block_align == 0 {
131 return Err(DemuxerError::NotImplemented);
132 }
133 let bits_per_sample = if csize >= 16 { self.src.read_u16le()? } else { 8 };
134 validate!(channels < 256);
135
61cab15b
KS
136 let edata = if csize > 16 {
137 validate!(csize >= 18);
138 let cb_size = self.src.read_u16le()? as usize;
139 let mut buf = vec![0; cb_size];
283abfa6 140 self.src.read_buf(buf.as_mut_slice())?;
61cab15b
KS
141 Some(buf)
142 } else {
143 None
144 };
283abfa6
KS
145
146 let cname = register::find_codec_from_wav_twocc(format_tag).unwrap_or("unknown");
147 let soniton = if cname == "pcm" {
148 if format_tag != 0x0003 {
149 if bits_per_sample == 8 {
150 NASoniton::new(8, 0)
151 } else {
152 NASoniton::new(bits_per_sample as u8, SONITON_FLAG_SIGNED)
153 }
154 } else {
155 NASoniton::new(bits_per_sample as u8, SONITON_FLAG_FLOAT)
156 }
157 } else {
158 NASoniton::new(bits_per_sample as u8, SONITON_FLAG_SIGNED)
159 };
160 let ahdr = NAAudioInfo::new(samples_per_sec, channels as u8, soniton, block_align);
161 let ainfo = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
162 let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, samples_per_sec));
163 if res.is_none() { return Err(MemoryError); }
164
165 self.srate = samples_per_sec;
166 self.block_size = block_align;
167 self.avg_bytes = avg_bytes_per_sec;
168 self.is_pcm = cname == "pcm";
169
170 Ok(())
171 }
172}
173
174pub struct WAVDemuxerCreator { }
175
176impl DemuxerCreator for WAVDemuxerCreator {
177 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
178 Box::new(WAVDemuxer::new(br))
179 }
180 fn get_name(&self) -> &'static str { "wav" }
181}
182
183#[cfg(test)]
184mod test {
185 use super::*;
186 use std::fs::File;
187
188 #[test]
189 fn test_wav_demux() {
190 let mut file = File::open("assets/MS/scatter.wav").unwrap();
191 let mut fr = FileReader::new_read(&mut file);
192 let mut br = ByteReader::new(&mut fr);
193 let mut dmx = WAVDemuxer::new(&mut br);
194 let mut sm = StreamManager::new();
195 let mut si = SeekIndex::new();
196 dmx.open(&mut sm, &mut si).unwrap();
197
198 loop {
199 let pktres = dmx.get_frame(&mut sm);
200 if let Err(e) = pktres {
201 if e == DemuxerError::EOF { break; }
202 panic!("error");
203 }
204 let pkt = pktres.unwrap();
205 println!("Got {}", pkt);
206 }
207 }
208}