]>
Commit | Line | Data |
---|---|---|
38953fb5 KS |
1 | use nihav_core::formats::*; |
2 | use nihav_core::codecs::*; | |
f5c54c10 | 3 | use nihav_core::io::byteio::*; |
3234da61 | 4 | |
67a31585 KS |
5 | #[derive(Clone,Copy,Debug,PartialEq)] |
6 | enum PCMMode { | |
7 | Infinity, | |
8 | ALaw, | |
9 | MuLaw, | |
10 | } | |
11 | ||
12 | struct PCMDecoder { | |
13 | chmap: NAChannelMap, | |
14 | mode: PCMMode, | |
15 | } | |
16 | ||
17 | fn cvt_alaw(val: u8) -> i16 { | |
18 | let val = val ^ 0x55; | |
19 | let sign = (val & 0x80) != 0; | |
20 | let exp = ((val >> 4) & 7) + 4; | |
21 | let mant = (val & 0xF) + if exp != 0 { 16 } else { 0 }; | |
22 | let aval = i16::from(mant) << exp; | |
23 | if sign { aval } else { -aval } | |
24 | } | |
25 | ||
26 | fn cvt_mulaw(val: u8) -> i16 { | |
27 | let val = !val; | |
28 | let sign = (val & 0x80) != 0; | |
29 | let exp = ((val >> 4) & 7) + 3; | |
30 | let mant = (val & 0xF) | 0x10; | |
31 | let aval = (i16::from(mant) << exp) - 128 - 4; | |
32 | if !sign { aval } else { -aval } | |
33 | } | |
3234da61 KS |
34 | |
35 | impl PCMDecoder { | |
67a31585 KS |
36 | fn new(mode: PCMMode) -> Self { |
37 | PCMDecoder { chmap: NAChannelMap::new(), mode } | |
38 | } | |
39 | fn decode_xlaw(&self, pkt: &NAPacket, duration: u64, srate: u32) -> DecoderResult<NAFrameRef> { | |
40 | let pktbuf = pkt.get_buffer(); | |
41 | let channels = self.chmap.num_channels(); | |
42 | let abuf = alloc_audio_buffer(NAAudioInfo::new(srate, channels as u8, SND_S16_FORMAT, 1), duration as usize, self.chmap.clone())?; | |
43 | let mut buf = abuf.get_abuf_i16().unwrap(); | |
44 | let dst = buf.get_data_mut().unwrap(); | |
45 | for (src, dst) in pktbuf.chunks(channels).zip(dst.chunks_mut(channels)) { | |
46 | for (isamp, dsamp) in src.iter().zip(dst.iter_mut()) { | |
47 | *dsamp = if self.mode == PCMMode::ALaw { cvt_alaw(*isamp) } else { cvt_mulaw(*isamp) }; | |
48 | } | |
49 | } | |
50 | let info = pkt.get_stream().get_info(); | |
51 | let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); | |
52 | frm.set_duration(Some(duration)); | |
53 | frm.set_keyframe(true); | |
54 | Ok(frm.into_ref()) | |
3234da61 KS |
55 | } |
56 | } | |
57 | ||
58 | const CHMAP_MONO: [NAChannelType; 1] = [NAChannelType::C]; | |
59 | const CHMAP_STEREO: [NAChannelType; 2] = [NAChannelType::L, NAChannelType::R]; | |
60 | ||
61 | fn get_default_chmap(nch: u8) -> NAChannelMap { | |
62 | let mut chmap = NAChannelMap::new(); | |
63 | match nch { | |
64 | 1 => chmap.add_channels(&CHMAP_MONO), | |
65 | 2 => chmap.add_channels(&CHMAP_STEREO), | |
66 | _ => (), | |
67 | } | |
68 | chmap | |
69 | } | |
70 | ||
12ccce74 | 71 | fn get_duration(ainfo: &NAAudioInfo, duration: Option<u64>, data_size: usize) -> u64 { |
3234da61 | 72 | if duration == None { |
12ccce74 | 73 | let size_bits = (data_size as u64) * 8; |
c83013a1 | 74 | let blk_size = u64::from(ainfo.get_channels()) * u64::from(ainfo.get_format().get_bits()); |
3234da61 KS |
75 | size_bits / blk_size |
76 | } else { | |
c83013a1 | 77 | duration.unwrap() |
3234da61 KS |
78 | } |
79 | } | |
80 | ||
81 | impl NADecoder for PCMDecoder { | |
01613464 | 82 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
3234da61 | 83 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { |
3234da61 KS |
84 | self.chmap = get_default_chmap(ainfo.get_channels()); |
85 | if self.chmap.num_channels() == 0 { return Err(DecoderError::InvalidData); } | |
86 | Ok(()) | |
87 | } else { | |
88 | Err(DecoderError::InvalidData) | |
89 | } | |
90 | } | |
01613464 | 91 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
3234da61 KS |
92 | let info = pkt.get_stream().get_info(); |
93 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { | |
94 | let duration = get_duration(&ainfo, pkt.get_duration(), pkt.get_buffer().len()); | |
67a31585 KS |
95 | if self.mode != PCMMode::Infinity { |
96 | return self.decode_xlaw(pkt, duration, ainfo.sample_rate); | |
97 | } | |
3234da61 | 98 | let pktbuf = pkt.get_buffer(); |
1a967e6b | 99 | let abuf = NAAudioBuffer::new_from_buf(ainfo, pktbuf, self.chmap.clone()); |
3234da61 | 100 | let mut frm = NAFrame::new_from_pkt(pkt, info, NABufferType::AudioPacked(abuf)); |
12ccce74 | 101 | frm.set_duration(Some(duration)); |
3234da61 | 102 | frm.set_keyframe(true); |
171860fc | 103 | Ok(frm.into_ref()) |
3234da61 KS |
104 | } else { |
105 | Err(DecoderError::InvalidData) | |
106 | } | |
107 | } | |
f9be4e75 KS |
108 | fn flush(&mut self) { |
109 | } | |
3234da61 KS |
110 | } |
111 | ||
7d57ae2f KS |
112 | impl NAOptionHandler for PCMDecoder { |
113 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
114 | fn set_options(&mut self, _options: &[NAOption]) { } | |
115 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
116 | } | |
117 | ||
08a1fab7 | 118 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { |
67a31585 KS |
119 | Box::new(PCMDecoder::new(PCMMode::Infinity)) |
120 | } | |
121 | ||
122 | pub fn get_a_law_decoder() -> Box<dyn NADecoder + Send> { | |
123 | Box::new(PCMDecoder::new(PCMMode::ALaw)) | |
124 | } | |
125 | ||
126 | pub fn get_mu_law_decoder() -> Box<dyn NADecoder + Send> { | |
127 | Box::new(PCMDecoder::new(PCMMode::MuLaw)) | |
3234da61 | 128 | } |
f5c54c10 KS |
129 | |
130 | struct PCMEncoder { | |
131 | stream: Option<NAStreamRef>, | |
132 | pkt: Option<NAPacket>, | |
133 | } | |
134 | ||
135 | impl PCMEncoder { | |
136 | fn new() -> Self { | |
137 | PCMEncoder { | |
138 | stream: None, | |
139 | pkt: None, | |
140 | } | |
141 | } | |
142 | } | |
143 | ||
144 | macro_rules! write_buffer { | |
145 | ($abuf: expr, $dvec: expr, $write_be: ident, $write_le: ident, $dtype: tt) => { | |
146 | let info = $abuf.get_info(); | |
147 | let len = $abuf.get_length(); | |
148 | let data = $abuf.get_data(); | |
149 | let channels = $abuf.get_chmap().num_channels(); | |
150 | let stride = $abuf.get_stride(); | |
151 | let step = $abuf.get_step(); | |
152 | let is_be = info.format.be; | |
153 | ||
154 | $dvec = vec![0u8; len * channels * std::mem::size_of::<$dtype>()]; | |
155 | let mut mw = MemoryWriter::new_write($dvec.as_mut_slice()); | |
156 | let mut bw = ByteWriter::new(&mut mw); | |
157 | for off in 0..len { | |
158 | for j in 0..channels { | |
159 | if is_be { | |
160 | bw.$write_be(data[off * step + j * stride] as $dtype).unwrap(); | |
161 | } else { | |
162 | bw.$write_le(data[off * step + j * stride] as $dtype).unwrap(); | |
163 | } | |
164 | } | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | impl NAEncoder for PCMEncoder { | |
170 | fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> { | |
171 | match encinfo.format { | |
172 | NACodecTypeInfo::None => { | |
173 | let mut ofmt = EncodeParameters::default(); | |
174 | ofmt.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_S16P_FORMAT, 0)); | |
175 | Ok(ofmt) | |
176 | }, | |
61cab15b | 177 | NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError), |
f5c54c10 KS |
178 | NACodecTypeInfo::Audio(_) => { |
179 | Ok(*encinfo) | |
180 | } | |
181 | } | |
182 | } | |
183 | fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> { | |
184 | match encinfo.format { | |
185 | NACodecTypeInfo::None => Err(EncoderError::FormatError), | |
186 | NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError), | |
187 | NACodecTypeInfo::Audio(_) => { | |
188 | let info = NACodecInfo::new("pcm", encinfo.format, None); | |
189 | let mut stream = NAStream::new(StreamType::Audio, stream_id, info, encinfo.tb_num, encinfo.tb_den); | |
190 | stream.set_num(stream_id as usize); | |
191 | let stream = stream.into_ref(); | |
192 | self.stream = Some(stream.clone()); | |
193 | Ok(stream) | |
194 | } | |
195 | } | |
196 | } | |
197 | fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> { | |
198 | let buf = frm.get_buffer(); | |
199 | let mut dbuf; | |
200 | match buf { | |
201 | NABufferType::AudioU8(ref abuf) => { | |
202 | let stride = abuf.get_stride(); | |
203 | if stride == 1 { // packed already | |
204 | self.pkt = Some(NAPacket::new_from_refbuf(self.stream.clone().unwrap(), frm.ts, true, abuf.get_data_ref())); | |
205 | return Ok(()); | |
206 | } | |
207 | let len = abuf.get_length(); | |
208 | let data = abuf.get_data(); | |
209 | let channels = abuf.get_chmap().num_channels(); | |
210 | dbuf = Vec::with_capacity(len * channels); | |
211 | for off in 0..len { | |
212 | for j in 0..channels { | |
213 | dbuf.push(data[off + j * stride]); | |
214 | } | |
215 | } | |
216 | }, | |
217 | NABufferType::AudioI16(ref abuf) => { | |
218 | write_buffer!(abuf, dbuf, write_u16be, write_u16le, u16); | |
219 | }, | |
220 | NABufferType::AudioI32(ref abuf) => { | |
221 | write_buffer!(abuf, dbuf, write_u32be, write_u32le, u32); | |
222 | }, | |
223 | NABufferType::AudioF32(ref abuf) => { | |
224 | write_buffer!(abuf, dbuf, write_f32be, write_f32le, f32); | |
225 | }, | |
226 | NABufferType::AudioPacked(ref abuf) => { | |
227 | self.pkt = Some(NAPacket::new_from_refbuf(self.stream.clone().unwrap(), frm.ts, true, abuf.get_data_ref())); | |
228 | return Ok(()); | |
229 | }, | |
230 | NABufferType::None => { | |
231 | self.pkt = None; | |
232 | return Ok(()); | |
233 | }, | |
234 | _ => return Err(EncoderError::FormatError), | |
235 | }; | |
236 | self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, true, dbuf)); | |
237 | Ok(()) | |
238 | } | |
239 | fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> { | |
240 | let mut npkt = None; | |
241 | std::mem::swap(&mut self.pkt, &mut npkt); | |
242 | Ok(npkt) | |
243 | } | |
244 | fn flush(&mut self) -> EncoderResult<()> { | |
245 | Ok(()) | |
246 | } | |
247 | } | |
248 | ||
249 | impl NAOptionHandler for PCMEncoder { | |
250 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
251 | fn set_options(&mut self, _options: &[NAOption]) { } | |
252 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
253 | } | |
254 | ||
255 | pub fn get_encoder() -> Box<dyn NAEncoder + Send> { | |
256 | Box::new(PCMEncoder::new()) | |
257 | } |