copy encoding parameters from the reference when negotiating the format
[nihav.git] / nihav-ms / src / codecs / msadpcm.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use std::str::FromStr;
4
5 const ADAPT_TABLE: [i32; 16] = [
6 230, 230, 230, 230, 307, 409, 512, 614,
7 768, 614, 512, 409, 307, 230, 230, 230
8 ];
9 const ADAPT_COEFFS: [[i32; 2]; 7] = [
10 [ 256, 0 ], [ 512, -256 ], [ 0, 0 ], [ 192, 64 ],
11 [ 240, 0 ], [ 460, -208 ], [ 392, -232 ]
12 ];
13
14 #[derive(Default)]
15 struct Predictor {
16 sample1: i32,
17 sample2: i32,
18 delta: i32,
19 coef1: i32,
20 coef2: i32,
21 }
22
23 impl Predictor {
24 fn expand_nibble(&mut self, nibble: u8) -> i16 {
25 let mul = if (nibble & 8) == 0 { i32::from(nibble) } else { i32::from(nibble) - 16 };
26 let pred = self.calc_pred() + self.delta.wrapping_mul(mul);
27 self.update(pred.max(-0x8000).min(0x7FFF));
28 self.delta = (ADAPT_TABLE[nibble as usize].wrapping_mul(self.delta) >> 8).max(16);
29 self.sample1 as i16
30 }
31 fn calc_pred(&self) -> i32 {
32 self.sample1.wrapping_mul(self.coef1).wrapping_add(self.sample2.wrapping_mul(self.coef2)) >> 8
33 }
34 fn update(&mut self, new_samp: i32) {
35 self.sample2 = self.sample1;
36 self.sample1 = new_samp;
37 }
38 }
39
40 struct MSADPCMDecoder {
41 ainfo: NAAudioInfo,
42 chmap: NAChannelMap,
43 adapt_coeffs: Vec<[i32; 2]>,
44 block_len: usize,
45 block_samps: usize,
46 }
47
48 impl MSADPCMDecoder {
49 fn new() -> Self {
50 Self {
51 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
52 chmap: NAChannelMap::new(),
53 adapt_coeffs: Vec::with_capacity(7),
54 block_len: 0,
55 block_samps: 0,
56 }
57 }
58 }
59
60 impl NADecoder for MSADPCMDecoder {
61 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
62 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
63 self.block_len = ainfo.get_block_len();
64 let channels = ainfo.get_channels() as usize;
65 validate!(channels == 2 || channels == 1);
66 validate!(self.block_len >= 7 * channels + 1);
67 self.block_samps = (self.block_len / channels - 7) * 2 + 2;
68 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), channels as u8, SND_S16P_FORMAT, self.block_samps);
69 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
70 self.adapt_coeffs.truncate(0);
71 if let Some(ref buf) = info.get_extradata() {
72 validate!(buf.len() >= 6);
73 validate!((buf.len() & 3) == 0);
74 let mut mr = MemoryReader::new_read(buf.as_slice());
75 let mut br = ByteReader::new(&mut mr);
76 let _smth = br.read_u16le()?;
77 let ncoeffs = br.read_u16le()? as usize;
78 validate!(buf.len() == ncoeffs * 4 + 4);
79
80 for _ in 0..ncoeffs {
81 let pair = [
82 i32::from(br.read_u16le()? as i16),
83 i32::from(br.read_u16le()? as i16)];
84 self.adapt_coeffs.push(pair);
85 }
86 } else {
87 self.adapt_coeffs.extend_from_slice(&ADAPT_COEFFS);
88 }
89 Ok(())
90 } else {
91 Err(DecoderError::InvalidData)
92 }
93 }
94 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
95 let info = pkt.get_stream().get_info();
96 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
97 let pktbuf = pkt.get_buffer();
98 let channels = self.chmap.num_channels();
99 validate!(pktbuf.len() > 0 && (pktbuf.len() % self.block_len) == 0);
100 let nblocks = pktbuf.len() / self.block_len;
101 let nsamples = nblocks * self.block_samps;
102 let abuf = alloc_audio_buffer(self.ainfo, nsamples, self.chmap.clone())?;
103 let mut adata = abuf.get_abuf_i16().unwrap();
104 let mut off = [adata.get_offset(0), adata.get_offset(1)];
105 let dst = adata.get_data_mut().unwrap();
106
107 let mut pred = [Predictor::default(), Predictor::default()];
108
109 for blk in pktbuf.chunks(self.block_len) {
110 let mut mr = MemoryReader::new_read(blk);
111 let mut br = ByteReader::new(&mut mr);
112 for ch in 0..channels {
113 let coef_idx = br.read_byte()? as usize;
114 validate!(coef_idx < self.adapt_coeffs.len());
115 pred[ch].coef1 = self.adapt_coeffs[coef_idx][0];
116 pred[ch].coef2 = self.adapt_coeffs[coef_idx][1];
117 }
118 for ch in 0..channels {
119 pred[ch].delta = i32::from(br.read_u16le()?);
120 }
121 for ch in 0..channels {
122 let samp = br.read_u16le()? as i16;
123 pred[ch].sample2 = i32::from(samp);
124 }
125 for ch in 0..channels {
126 let samp = br.read_u16le()? as i16;
127 pred[ch].sample1 = i32::from(samp);
128 }
129 for ch in 0..channels {
130 dst[off[ch]] = pred[ch].sample2 as i16;
131 dst[off[ch] + 1] = pred[ch].sample1 as i16;
132 off[ch] += 2;
133 }
134 if channels == 1 {
135 while br.left() > 0 {
136 let idx = br.read_byte()?;
137 dst[off[0]] = pred[0].expand_nibble(idx >> 4);
138 off[0] += 1;
139 dst[off[0]] = pred[0].expand_nibble(idx & 0xF);
140 off[0] += 1;
141 }
142 } else {
143 while br.left() > 0 {
144 let idx = br.read_byte()?;
145 dst[off[0]] = pred[0].expand_nibble(idx >> 4);
146 off[0] += 1;
147 dst[off[1]] = pred[1].expand_nibble(idx & 0xF);
148 off[1] += 1;
149 }
150 }
151 }
152 let mut frm = NAFrame::new_from_pkt(pkt, info.replace_info(NACodecTypeInfo::Audio(self.ainfo)), abuf);
153 frm.set_duration(Some(nsamples as u64));
154 frm.set_keyframe(false);
155 Ok(frm.into_ref())
156 } else {
157 Err(DecoderError::InvalidData)
158 }
159 }
160 fn flush(&mut self) {
161 }
162 }
163
164 impl NAOptionHandler for MSADPCMDecoder {
165 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
166 fn set_options(&mut self, _options: &[NAOption]) { }
167 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
168 }
169
170 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
171 Box::new(MSADPCMDecoder::new())
172 }
173
174 #[derive(Default)]
175 struct MSADPCMEncoder {
176 stream: Option<NAStreamRef>,
177 samples: Vec<i16>,
178 block_len: usize,
179 channels: usize,
180 flush: bool,
181 srate: u32,
182 }
183
184 const DEFAULT_BLOCK_LEN: usize = 256;
185
186 impl MSADPCMEncoder {
187 fn new() -> Self { Self::default() }
188 fn encode_packet(&mut self) -> EncoderResult<NAPacket> {
189 if self.samples.len() == 0 {
190 return Err(EncoderError::TryAgain);
191 }
192 let len = (self.samples.len() / self.channels).min(self.block_len);
193 if len < self.block_len && !self.flush {
194 return Err(EncoderError::TryAgain);
195 }
196 if len < 2 {
197 self.flush = false;
198 return Err(EncoderError::TryAgain);
199 }
200
201 let mut dbuf = vec![0u8; Self::calc_block_size(len, self.channels)];
202 let mut mw = MemoryWriter::new_write(dbuf.as_mut_slice());
203 let mut bw = ByteWriter::new(&mut mw);
204
205 let mut best_idx = [0usize; 2];
206 for ch in 0..self.channels {
207 let mut best_dist = std::i64::MAX;
208 for i in 0..ADAPT_COEFFS.len() {
209 let dist = self.calc_dist(ch, i, len);
210 if dist < best_dist {
211 best_dist = dist;
212 best_idx[ch] = i;
213 }
214 }
215 bw.write_byte(best_idx[ch] as u8)?;
216 }
217 let mut dec = [Predictor::default(), Predictor::default()];
218 for ch in 0..self.channels {
219 dec[ch].sample1 = i32::from(self.samples[ch + self.channels]);
220 dec[ch].sample2 = i32::from(self.samples[ch]);
221 dec[ch].coef1 = ADAPT_COEFFS[best_idx[ch]][0];
222 dec[ch].coef2 = ADAPT_COEFFS[best_idx[ch]][1];
223 if len > 2 {
224 let pred = dec[ch].calc_pred();
225 dec[ch].delta = ((i32::from(self.samples[ch + self.channels * 2]) - pred).abs() / 4).max(16);
226 } else {
227 dec[ch].delta = 16;
228 }
229 }
230 for ch in 0..self.channels {
231 bw.write_u16le(dec[ch].delta as u16)?;
232 }
233 for ch in 0..self.channels {
234 bw.write_u16le(dec[ch].sample1 as u16)?;
235 }
236 for ch in 0..self.channels {
237 bw.write_u16le(dec[ch].sample2 as u16)?;
238 }
239 if self.channels == 1 {
240 for samps in self.samples.chunks(2).skip(1).take(len/2 - 1) {
241 let diff = i32::from(samps[0]) - dec[0].calc_pred();
242 let nib0 = Self::calculate_mul(dec[0].delta, diff);
243 dec[0].expand_nibble(nib0);
244 let diff = i32::from(samps[1]) - dec[0].calc_pred();
245 let nib1 = Self::calculate_mul(dec[0].delta, diff);
246 dec[0].expand_nibble(nib1);
247 bw.write_byte(nib0 * 16 + nib1)?;
248 }
249 } else {
250 for samps in self.samples.chunks(2).skip(2).take(len - 2) {
251 let diff = i32::from(samps[0]) - dec[0].calc_pred();
252 let nib0 = Self::calculate_mul(dec[0].delta, diff);
253 dec[0].expand_nibble(nib0);
254 let diff = i32::from(samps[1]) - dec[1].calc_pred();
255 let nib1 = Self::calculate_mul(dec[1].delta, diff);
256 dec[1].expand_nibble(nib1);
257 bw.write_byte(nib0 * 16 + nib1)?;
258 }
259 }
260 self.samples.drain(..len * self.channels);
261 drop(bw);
262 let ts = NATimeInfo::new(None, None, Some(1), 1, self.srate);
263 Ok(NAPacket::new(self.stream.clone().unwrap(), ts, true, dbuf))
264 }
265 fn calc_dist(&self, ch: usize, idx: usize, len: usize) -> i64 {
266 let mut dist = 0;
267 let mut dec = Predictor {
268 sample2: i32::from(self.samples[ch]),
269 sample1: i32::from(self.samples[ch + self.channels]),
270 coef1: ADAPT_COEFFS[idx][0],
271 coef2: ADAPT_COEFFS[idx][1],
272 delta: 16,
273 };
274 if self.channels == 1 {
275 for samp in self.samples.iter().skip(2).take(len - 2) {
276 let pred = dec.calc_pred();
277 dec.update(pred);
278 let diff = i64::from(*samp) - i64::from(pred);
279 dist += diff * diff;
280 }
281 } else {
282 for samp in self.samples.chunks(2).skip(2).take(len - 2) {
283 let pred = dec.calc_pred();
284 dec.update(pred);
285 let diff = i64::from(samp[ch]) - i64::from(pred);
286 dist += diff * diff;
287 }
288 }
289 dist
290 }
291 fn calculate_mul(delta: i32, diff: i32) -> u8 {
292 ((diff / delta).max(-8).min(7) & 0xF) as u8
293 }
294 fn calc_block_size(nsamps: usize, channels: usize) -> usize {
295 (nsamps - 2) * channels / 2 + 7 * channels
296 }
297 }
298
299 impl NAEncoder for MSADPCMEncoder {
300 fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> {
301 match encinfo.format {
302 NACodecTypeInfo::None => {
303 let mut ofmt = EncodeParameters::default();
304 ofmt.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 1, SND_S16_FORMAT, DEFAULT_BLOCK_LEN));
305 return Ok(ofmt);
306 },
307 NACodecTypeInfo::Video(_) => return Err(EncoderError::FormatError),
308 NACodecTypeInfo::Audio(ainfo) => {
309 let mut outinfo = ainfo;
310 outinfo.channels = outinfo.channels.min(2);
311 if outinfo.format != SND_S16P_FORMAT && outinfo.format != SND_S16_FORMAT {
312 outinfo.format = SND_S16_FORMAT;
313 }
314 if outinfo.block_len == 0 {
315 outinfo.block_len = DEFAULT_BLOCK_LEN;
316 }
317 if outinfo.block_len < 2 {
318 outinfo.block_len = 2;
319 }
320 if (outinfo.channels == 1) && ((outinfo.block_len & 1) == 1) {
321 outinfo.block_len += 1;
322 }
323 let mut ofmt = *encinfo;
324 ofmt.format = NACodecTypeInfo::Audio(outinfo);
325 return Ok(ofmt);
326 }
327 };
328 }
329 fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> {
330 match encinfo.format {
331 NACodecTypeInfo::None => Err(EncoderError::FormatError),
332 NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError),
333 NACodecTypeInfo::Audio(ainfo) => {
334 if ainfo.format != SND_S16P_FORMAT && ainfo.format != SND_S16_FORMAT {
335 return Err(EncoderError::FormatError);
336 }
337 if ainfo.channels != 1 && ainfo.channels != 2 {
338 return Err(EncoderError::FormatError);
339 }
340 if ainfo.block_len < 2 || ((ainfo.block_len * (ainfo.channels as usize)) & 1) != 0 {
341 return Err(EncoderError::FormatError);
342 }
343 self.channels = ainfo.channels as usize;
344 self.block_len = ainfo.block_len;
345
346 let soniton = NASoniton::new(4, 0);
347 let out_ainfo = NAAudioInfo::new(ainfo.sample_rate, ainfo.channels, soniton, Self::calc_block_size(self.block_len, self.channels));
348 let info = NACodecInfo::new("ms-adpcm", NACodecTypeInfo::Audio(out_ainfo), None);
349 let stream = NAStream::new(StreamType::Audio, stream_id, info.clone(), self.block_len as u32, ainfo.sample_rate).into_ref();
350
351 self.stream = Some(stream.clone());
352 self.samples = Vec::with_capacity(self.block_len * self.channels);
353 self.srate = ainfo.sample_rate;
354 self.flush = false;
355
356 Ok(stream)
357 },
358 }
359 }
360 fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> {
361 let buf = frm.get_buffer();
362 if let Some(ref abuf) = buf.get_abuf_i16() {
363 let src = abuf.get_data();
364 let len = abuf.get_length();
365 let ch = abuf.get_chmap().num_channels();
366 if abuf.get_step() > 1 || ch == 1 {
367 self.samples.extend(src.iter().take(len * ch));
368 } else {
369 let (src0, src1) = src.split_at(abuf.get_stride());
370 self.samples.reserve(len * 2);
371 for (s0, s1) in src0.iter().take(len).zip(src1.iter()) {
372 self.samples.push(*s0);
373 self.samples.push(*s1);
374 }
375 }
376 Ok(())
377 } else {
378 Err(EncoderError::InvalidParameters)
379 }
380 }
381 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
382 if let Ok(pkt) = self.encode_packet() {
383 Ok(Some(pkt))
384 } else {
385 Ok(None)
386 }
387 }
388 fn flush(&mut self) -> EncoderResult<()> {
389 self.flush = true;
390 Ok(())
391 }
392 }
393
394 impl NAOptionHandler for MSADPCMEncoder {
395 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
396 fn set_options(&mut self, _options: &[NAOption]) { }
397 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
398 }
399
400 pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
401 Box::new(MSADPCMEncoder::new())
402 }
403
404 #[cfg(test)]
405 mod test {
406 use nihav_core::codecs::*;
407 use nihav_core::demuxers::*;
408 use nihav_core::muxers::*;
409 use nihav_codec_support::test::dec_video::*;
410 use nihav_codec_support::test::enc_video::*;
411 use crate::*;
412 use nihav_commonfmt::*;
413 #[cfg(feature="decoder_ms_adpcm")]
414 #[test]
415 fn test_ms_adpcm_decoder() {
416 let mut dmx_reg = RegisteredDemuxers::new();
417 generic_register_all_demuxers(&mut dmx_reg);
418 let mut dec_reg = RegisteredDecoders::new();
419 ms_register_all_codecs(&mut dec_reg);
420
421 test_decoding("avi", "ms-adpcm", "assets/MS/dance.avi", None, &dmx_reg, &dec_reg,
422 ExpectedTestResult::MD5([0x9d6619e1, 0x60d83560, 0xfe5c1fb7, 0xad5d130d]));
423 }
424 #[cfg(feature="encoder_ms_adpcm")]
425 #[test]
426 fn test_ms_adpcm_encoder() {
427 let mut dmx_reg = RegisteredDemuxers::new();
428 generic_register_all_demuxers(&mut dmx_reg);
429 let mut dec_reg = RegisteredDecoders::new();
430 generic_register_all_codecs(&mut dec_reg);
431 ms_register_all_codecs(&mut dec_reg);
432 let mut mux_reg = RegisteredMuxers::new();
433 generic_register_all_muxers(&mut mux_reg);
434 let mut enc_reg = RegisteredEncoders::new();
435 ms_register_all_encoders(&mut enc_reg);
436
437 let dec_config = DecoderTestParams {
438 demuxer: "avi",
439 in_name: "assets/Indeo/laser05.avi",
440 stream_type: StreamType::Audio,
441 limit: None,
442 dmx_reg, dec_reg,
443 };
444 let enc_config = EncoderTestParams {
445 muxer: "wav",
446 enc_name: "ms-adpcm",
447 out_name: "msadpcm.wav",
448 mux_reg, enc_reg,
449 };
450 let dst_ainfo = NAAudioInfo {
451 sample_rate: 0,
452 channels: 0,
453 format: SND_S16_FORMAT,
454 block_len: 128,
455 };
456 let enc_params = EncodeParameters {
457 format: NACodecTypeInfo::Audio(dst_ainfo),
458 quality: 0,
459 bitrate: 0,
460 tb_num: 0,
461 tb_den: 0,
462 flags: 0,
463 };
464 test_encoding_to_file(&dec_config, &enc_config, enc_params);
465 }
466 }