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