]>
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, | |
22 | } | |
23 | ||
24 | impl<'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; | |
28 | let riff_end = self.src.tell() + if riff_size > 0 { (riff_size as u64) } else { u64::from(std::u32::MAX) }; | |
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 | ||
86 | fn seek(&mut self, time: u64, _seek_index: &SeekIndex) -> DemuxerResult<()> { | |
87 | if self.block_size != 0 && self.avg_bytes != 0 { | |
88 | let seek_dst = u64::from(self.avg_bytes) * time / 1000; | |
89 | let seek_off = seek_dst / (self.block_size as u64) * (self.block_size as u64); | |
90 | self.src.seek(SeekFrom::Start(self.data_pos + seek_off))?; | |
91 | Ok(()) | |
92 | } else { | |
93 | Err(DemuxerError::NotImplemented) | |
94 | } | |
95 | } | |
96 | } | |
97 | ||
787b8d03 KS |
98 | impl<'a> NAOptionHandler for WAVDemuxer<'a> { |
99 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
100 | fn set_options(&mut self, _options: &[NAOption]) { } | |
101 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
102 | } | |
103 | ||
283abfa6 KS |
104 | impl<'a> WAVDemuxer<'a> { |
105 | fn new(io: &'a mut ByteReader<'a>) -> Self { | |
106 | WAVDemuxer { | |
107 | src: io, | |
108 | data_pos: 0, | |
109 | data_end: 0, | |
110 | srate: 0, | |
111 | block_size: 0, | |
112 | is_pcm: false, | |
113 | avg_bytes: 0, | |
114 | } | |
115 | } | |
116 | fn parse_fmt(&mut self, strmgr: &mut StreamManager, csize: usize) -> DemuxerResult<()> { | |
117 | validate!(csize >= 14); | |
118 | let format_tag = self.src.read_u16le()?; | |
119 | let channels = self.src.read_u16le()?; | |
120 | validate!(channels < 256); | |
121 | let samples_per_sec = self.src.read_u32le()?; | |
122 | let avg_bytes_per_sec = self.src.read_u32le()?; | |
123 | let block_align = self.src.read_u16le()? as usize; | |
124 | if block_align == 0 { | |
125 | return Err(DemuxerError::NotImplemented); | |
126 | } | |
127 | let bits_per_sample = if csize >= 16 { self.src.read_u16le()? } else { 8 }; | |
128 | validate!(channels < 256); | |
129 | ||
61cab15b KS |
130 | let edata = if csize > 16 { |
131 | validate!(csize >= 18); | |
132 | let cb_size = self.src.read_u16le()? as usize; | |
133 | let mut buf = vec![0; cb_size]; | |
283abfa6 | 134 | self.src.read_buf(buf.as_mut_slice())?; |
61cab15b KS |
135 | Some(buf) |
136 | } else { | |
137 | None | |
138 | }; | |
283abfa6 KS |
139 | |
140 | let cname = register::find_codec_from_wav_twocc(format_tag).unwrap_or("unknown"); | |
141 | let soniton = if cname == "pcm" { | |
142 | if format_tag != 0x0003 { | |
143 | if bits_per_sample == 8 { | |
144 | NASoniton::new(8, 0) | |
145 | } else { | |
146 | NASoniton::new(bits_per_sample as u8, SONITON_FLAG_SIGNED) | |
147 | } | |
148 | } else { | |
149 | NASoniton::new(bits_per_sample as u8, SONITON_FLAG_FLOAT) | |
150 | } | |
151 | } else { | |
152 | NASoniton::new(bits_per_sample as u8, SONITON_FLAG_SIGNED) | |
153 | }; | |
154 | let ahdr = NAAudioInfo::new(samples_per_sec, channels as u8, soniton, block_align); | |
155 | let ainfo = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata); | |
156 | let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, samples_per_sec)); | |
157 | if res.is_none() { return Err(MemoryError); } | |
158 | ||
159 | self.srate = samples_per_sec; | |
160 | self.block_size = block_align; | |
161 | self.avg_bytes = avg_bytes_per_sec; | |
162 | self.is_pcm = cname == "pcm"; | |
163 | ||
164 | Ok(()) | |
165 | } | |
166 | } | |
167 | ||
168 | pub struct WAVDemuxerCreator { } | |
169 | ||
170 | impl DemuxerCreator for WAVDemuxerCreator { | |
171 | fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> { | |
172 | Box::new(WAVDemuxer::new(br)) | |
173 | } | |
174 | fn get_name(&self) -> &'static str { "wav" } | |
175 | } | |
176 | ||
177 | #[cfg(test)] | |
178 | mod test { | |
179 | use super::*; | |
180 | use std::fs::File; | |
181 | ||
182 | #[test] | |
183 | fn test_wav_demux() { | |
184 | let mut file = File::open("assets/MS/scatter.wav").unwrap(); | |
185 | let mut fr = FileReader::new_read(&mut file); | |
186 | let mut br = ByteReader::new(&mut fr); | |
187 | let mut dmx = WAVDemuxer::new(&mut br); | |
188 | let mut sm = StreamManager::new(); | |
189 | let mut si = SeekIndex::new(); | |
190 | dmx.open(&mut sm, &mut si).unwrap(); | |
191 | ||
192 | loop { | |
193 | let pktres = dmx.get_frame(&mut sm); | |
194 | if let Err(e) = pktres { | |
195 | if e == DemuxerError::EOF { break; } | |
196 | panic!("error"); | |
197 | } | |
198 | let pkt = pktres.unwrap(); | |
199 | println!("Got {}", pkt); | |
200 | } | |
201 | } | |
202 | } |