From: Kostya Shishkov Date: Sat, 23 Aug 2025 12:33:50 +0000 (+0200) Subject: ATSC A/52B packetiser X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=6e636079d5d7eb917a9a5f46c1c23975e3c0051d;p=nihav.git ATSC A/52B packetiser --- diff --git a/nihav-allstuff/src/lib.rs b/nihav-allstuff/src/lib.rs index 08bca93..034672c 100644 --- a/nihav-allstuff/src/lib.rs +++ b/nihav-allstuff/src/lib.rs @@ -50,6 +50,7 @@ pub fn nihav_register_all_mt_decoders(rd: &mut RegisteredMTDecoders) { /// Registers all known packetisers. pub fn nihav_register_all_packetisers(rp: &mut RegisteredPacketisers) { acorn_register_all_packetisers(rp); + generic_register_all_packetisers(rp); llaudio_register_all_packetisers(rp); mpeg_register_all_packetisers(rp); } diff --git a/nihav-commonfmt/src/codecs/mod.rs b/nihav-commonfmt/src/codecs/mod.rs index 536bfa3..7e85553 100644 --- a/nihav-commonfmt/src/codecs/mod.rs +++ b/nihav-commonfmt/src/codecs/mod.rs @@ -117,3 +117,14 @@ pub fn generic_register_all_encoders(re: &mut RegisteredEncoders) { } } +const PACKETISERS: &[PacketiserInfo] = &[ +#[cfg(feature="decoder_ts102366")] + PacketiserInfo { name: "ac3", get_packetiser: ts102366::get_packetiser }, +]; + +/// Registers all available packetisers provided by this crate. +pub fn generic_register_all_packetisers(rp: &mut RegisteredPacketisers) { + for packetiser in PACKETISERS.iter() { + rp.add_packetiser(*packetiser); + } +} diff --git a/nihav-commonfmt/src/codecs/ts102366.rs b/nihav-commonfmt/src/codecs/ts102366.rs index 399f231..729d94c 100644 --- a/nihav-commonfmt/src/codecs/ts102366.rs +++ b/nihav-commonfmt/src/codecs/ts102366.rs @@ -20,6 +20,8 @@ const STRATEGY_REUSE: u8 = 0; const LFE_CHANNEL: usize = MAX_CHANNELS; const CPL_CHANNEL: usize = MAX_CHANNELS + 1; +const SYNCINFO_BITS: u32 = 40; + struct IMDCTContext { xsincos: [FFTComplex; BLOCK_LEN/2], fft: FFT, @@ -1251,6 +1253,153 @@ pub fn get_decoder() -> Box { Box::new(AudioDecoder::new()) } +#[derive(Default)] +struct AudioPacketiser { + buf: Vec, + hdr: Option, + is_be: Option, +} + +impl AudioPacketiser { + fn new() -> Self { Self::default() } + fn parse_header(&self, off: usize) -> DecoderResult<(Syncinfo, bool)> { + if self.buf.len() < off + 5 { return Err(DecoderError::ShortData); } + + let (mut br, is_be) = if (self.buf[off] == MAGIC_BYTE0) && (self.buf[off + 1] == MAGIC_BYTE1) { + (BitReader::new(&self.buf[off..], BitReaderMode::BE), true) + } else if (self.buf[off] == MAGIC_BYTE1) && (self.buf[off + 1] == MAGIC_BYTE0) { + (BitReader::new(&self.buf[off..], BitReaderMode::LE16MSB), false) + } else { + return Err(DecoderError::InvalidData); + }; + + if let Some(ref_is_be) = self.is_be { + if ref_is_be != is_be { + return Err(DecoderError::InvalidData); + } + } + + let sinfo = Syncinfo::read(&mut br)?; + if !sinfo.is_valid() { return Err(DecoderError::InvalidData); } + + Ok((sinfo, is_be)) + } +} + +impl NAPacketiser for AudioPacketiser { + fn attach_stream(&mut self, _stream: NAStreamRef) {} + fn add_data(&mut self, src: &[u8]) -> bool { + self.buf.extend_from_slice(src); + self.buf.len() < 4096 + } + fn parse_stream(&mut self, id: u32) -> DecoderResult { + if self.hdr.is_none() { + if self.buf.len() < 16 { + return Err(DecoderError::ShortData); + } + let (hdr, is_be) = self.parse_header(0)?; + self.hdr = Some(hdr); + self.is_be = Some(is_be); + } + let hdr = self.hdr.unwrap(); + + let mut br = if let Some(true) = self.is_be { + BitReader::new(self.buf.as_slice(), BitReaderMode::BE) + } else { + BitReader::new(self.buf.as_slice(), BitReaderMode::LE16MSB) + }; + br.skip(SYNCINFO_BITS)?; + let bsi = BSI::read(&mut br)?; + + let core_channels = bsi.acmod.get_num_channels(); + let channels = core_channels + if bsi.lfeon { 1 } else { 0 }; + + let ainfo = NAAudioInfo::new(hdr.samplerate >> bsi.shift, channels as u8, + SND_F32P_FORMAT, BLOCK_LEN); + let info = NACodecInfo::new("ac3", NACodecTypeInfo::Audio(ainfo), None); + Ok(NAStream::new(StreamType::Audio, id, info, (NBLOCKS * BLOCK_LEN) as u32, hdr.samplerate >> bsi.shift, 0).into_ref()) + } + fn skip_junk(&mut self) -> DecoderResult { + if self.buf.len() <= 2 { + return Ok(0); + } + let mut off = 0; + let mut hdr = u16::from(self.buf[0]) * 256 + u16::from(self.buf[1]); + let mut iter = self.buf[2..].iter(); + const BE_SIG: u16 = (MAGIC_BYTE0 as u16) * 256 + (MAGIC_BYTE1 as u16); + const LE_SIG: u16 = (MAGIC_BYTE1 as u16) * 256 + (MAGIC_BYTE0 as u16); + loop { + if (hdr == BE_SIG && self.is_be != Some(false)) || (hdr == LE_SIG && self.is_be != Some(true)) { + let ret = self.parse_header(off); + match ret { + Ok((hdr, is_be)) => { + if self.hdr.is_none() { + self.hdr = Some(hdr); + self.is_be = Some(is_be); + } + let ref_hdr = self.hdr.unwrap(); + if ref_hdr.samplerate != hdr.samplerate { // header is valid but mismatches + self.buf.drain(..off + 1); + return Err(DecoderError::InvalidData); + } + break; + }, + Err(err) => { + self.buf.drain(..off + 1); + return Err(err); + }, + }; + } + off += 1; + if let Some(&b) = iter.next() { + hdr = (hdr << 8) | u16::from(b); + } else { + break; + } + } + self.buf.drain(..off); + Ok(off) + } + fn get_packet(&mut self, stream: NAStreamRef) -> DecoderResult> { + if self.buf.len() < 16 { + return Err(DecoderError::ShortData); + } + let (hdr, _) = self.parse_header(0)?; + if self.hdr.is_none() { + self.hdr = Some(hdr); + } + let ref_hdr = self.hdr.unwrap(); + if ref_hdr.samplerate != hdr.samplerate { // header is valid but mismatches + return Err(DecoderError::InvalidData); + } + if hdr.frame_size <= self.buf.len() { + let mut br = if let Some(true) = self.is_be { + BitReader::new(self.buf.as_slice(), BitReaderMode::BE) + } else { + BitReader::new(self.buf.as_slice(), BitReaderMode::LE16MSB) + }; + br.skip(SYNCINFO_BITS)?; + let bsi = BSI::read(&mut br)?; + + let mut data = Vec::with_capacity(hdr.frame_size); + data.extend_from_slice(&self.buf[..hdr.frame_size]); + self.buf.drain(..hdr.frame_size); + let ts = NATimeInfo::new(None, None, Some(1), (NBLOCKS * BLOCK_LEN) as u32, hdr.samplerate >> bsi.shift); + Ok(Some(NAPacket::new(stream, ts, true, data))) + } else { + Ok(None) + } + } + fn reset(&mut self) { + self.buf.clear(); + } + fn bytes_left(&self) -> usize { self.buf.len() } +} + +pub fn get_packetiser() -> Box { + Box::new(AudioPacketiser::new()) +} + #[cfg(test)] mod test { use nihav_core::codecs::RegisteredDecoders; diff --git a/nihav-commonfmt/src/lib.rs b/nihav-commonfmt/src/lib.rs index beda083..f4f918e 100644 --- a/nihav-commonfmt/src/lib.rs +++ b/nihav-commonfmt/src/lib.rs @@ -10,6 +10,8 @@ mod codecs; #[cfg(feature="decoders")] pub use crate::codecs::generic_register_all_decoders; +#[cfg(feature="decoders")] +pub use crate::codecs::generic_register_all_packetisers; #[cfg(feature="encoders")] pub use crate::codecs::generic_register_all_encoders;