From: Kostya Shishkov Date: Thu, 25 May 2023 15:46:15 +0000 (+0200) Subject: improve audio conversion X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=6f6ba7bfe78bfbd3eff7145bf98839b21213df04;p=nihav-encoder.git improve audio conversion --- diff --git a/src/acvt.rs b/src/acvt.rs index 5343039..349e10b 100644 --- a/src/acvt.rs +++ b/src/acvt.rs @@ -39,11 +39,18 @@ impl> AudioQueue { let old_len = self.get_cur_size(); let new_len = src.get_length(); - for (dst, (old, new)) in new_buf.chunks_exact_mut(new_stride).zip( - self.data.chunks_exact(self.stride).zip( - src.get_data().chunks(src.get_stride()))) { - dst[..old_len].copy_from_slice(&old[self.start..self.end]); - dst[old_len..][..new_len].copy_from_slice(&new[..new_len]); + if old_len > 0 { + for (dst, (old, new)) in new_buf.chunks_exact_mut(new_stride).zip( + self.data.chunks_exact(self.stride).zip( + src.get_data().chunks(src.get_stride()))) { + dst[..old_len].copy_from_slice(&old[self.start..self.end]); + dst[old_len..][..new_len].copy_from_slice(&new[..new_len]); + } + } else { + for (dst, new) in new_buf.chunks_exact_mut(new_stride).zip( + src.get_data().chunks(src.get_stride())) { + dst[..new_len].copy_from_slice(&new[..new_len]); + } } self.data = new_buf; self.stride = new_stride; @@ -110,10 +117,11 @@ pub struct AudioConverter { dst_fmt: NAAudioInfo, dst_chmap: NAChannelMap, apts: Option, + resampler: NAResample, } impl AudioConverter { - pub fn new(_sinfo: &NAAudioInfo, dinfo: &NAAudioInfo, dst_chmap: NAChannelMap) -> Self { + pub fn new(sinfo: &NAAudioInfo, dinfo: &NAAudioInfo, dst_chmap: NAChannelMap) -> Self { let ch = usize::from(dinfo.channels); let size = dinfo.block_len * 2; let il = !dinfo.format.planar; @@ -124,15 +132,18 @@ impl AudioConverter { (32, true, _) => AudioDataType::F32(AudioQueue::new(ch, size, il)), _ => AudioDataType::Packed(AudioQueue::new(ch, size, il)), }; + const RESAMPLE_FILTER_ORDER: usize = 16; + let resampler = NAResample::new(sinfo.sample_rate, dinfo, &dst_chmap, RESAMPLE_FILTER_ORDER); Self { queue, dst_fmt: *dinfo, dst_chmap, apts: None, + resampler, } } pub fn queue_frame(&mut self, buf: NABufferType, tinfo: NATimeInfo) -> bool { - let ret = convert_audio_frame(&buf, &self.dst_fmt, &self.dst_chmap); + let ret = self.resampler.convert_audio_frame(&buf); if let Ok(dbuf) = ret { if self.apts.is_none() && tinfo.get_pts().is_some() { self.apts = tinfo.get_pts(); diff --git a/src/main.rs b/src/main.rs index 1958bed..e033dfd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,8 @@ mod null; mod acvt; use crate::acvt::*; +const SND_NO_FORMAT: NASoniton = NASoniton { bits: 0, be: false, packed: false, planar: false, float: false, signed: false }; + fn format_time(ms: u64) -> String { let s = ms / 1000; let ds = (ms % 1000) / 100; @@ -316,7 +318,7 @@ impl Transcoder { }, "srate" => { if ostr.enc_params.format == NACodecTypeInfo::None { - ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_S16_FORMAT, 0)); + ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0)); } if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format { let ret = oval[1].parse::(); @@ -331,7 +333,7 @@ impl Transcoder { }, "channels" => { if ostr.enc_params.format == NACodecTypeInfo::None { - ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_S16_FORMAT, 0)); + ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0)); } if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format { let ret = oval[1].parse::(); @@ -346,7 +348,7 @@ impl Transcoder { }, "block_len" => { if ostr.enc_params.format == NACodecTypeInfo::None { - ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_S16_FORMAT, 0)); + ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0)); } if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format { let ret = oval[1].parse::(); @@ -361,7 +363,7 @@ impl Transcoder { }, "sfmt" => { if ostr.enc_params.format == NACodecTypeInfo::None { - ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_S16_FORMAT, 0)); + ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0)); } if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format { let ret = oval[1].parse::(); @@ -377,7 +379,7 @@ impl Transcoder { // todo channel map negotiation /*"chmap" => { if ostr.enc_params.format == NACodecTypeInfo::None { - ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_S16_FORMAT, 0)); + ostr.enc_params.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_NO_FORMAT, 0)); } if let NACodecTypeInfo::Audio(ref mut ainfo) = ostr.enc_params.format { let ret = oval[1].parse::(); @@ -502,8 +504,35 @@ impl Transcoder { } let mut encoder = (enc_create.unwrap())(); let forced_out = oopts.enc_params.format != NACodecTypeInfo::None; + let iformat = istr.get_info().get_properties(); if oopts.enc_params.format == NACodecTypeInfo::None { oopts.enc_params.format = istr.get_info().get_properties(); + } else { + match (&iformat, &mut oopts.enc_params.format) { + (NACodecTypeInfo::Video(svinfo), NACodecTypeInfo::Video(ref mut dvinfo)) => { + if dvinfo.width == 0 { + dvinfo.width = svinfo.width; + } + if dvinfo.height == 0 { + dvinfo.height = svinfo.height; + } + }, + (NACodecTypeInfo::Audio(sainfo), NACodecTypeInfo::Audio(ref mut dainfo)) => { + if dainfo.sample_rate == 0 { + dainfo.sample_rate = sainfo.sample_rate; + } + if dainfo.format == SND_NO_FORMAT { + dainfo.format = sainfo.format; + } + if dainfo.channels == 0 { + dainfo.channels = sainfo.channels; + } + if dainfo.block_len == 0 { + dainfo.block_len = sainfo.block_len; + } + }, + _ => {}, + }; } if oopts.enc_params.tb_num == 0 { oopts.enc_params.tb_num = istr.tb_num; @@ -517,7 +546,7 @@ impl Transcoder { let ret_eparams = ret_eparams.unwrap(); //todo check for params mismatch - let cvt = match (&oopts.enc_params.format, &ret_eparams.format) { + let cvt = match (&iformat, &ret_eparams.format) { (NACodecTypeInfo::Video(svinfo), NACodecTypeInfo::Video(dvinfo)) => { if svinfo == dvinfo && !forced_out { OutputConvert::None