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