mod tools;
use tools::*;
+mod packetiser;
+pub use packetiser::get_packetiser_adts;
+
const MAX_WINDOWS: usize = 8;
const MAX_SFBS: usize = 64;
use nihav_codec_support::test::dec_video::test_decode_audio;
use crate::mpeg_register_all_decoders;
use nihav_realmedia::realmedia_register_all_demuxers;
+ use std::io::Read;
+
#[test]
fn test_aac() {
let mut dmx_reg = RegisteredDemuxers::new();
let file = "assets/MPEG/SBRtestStereoAot29Sig0.mp4";
test_decode_audio("mov", file, Some(400), None/*Some("aacsbr")*/, &dmx_reg, &dec_reg);
}
+ #[test]
+ fn test_adts_packetiser() {
+ let mut buf = [0; 4096];
+ // sample obtained with yt-dlp -f 234
+ let mut file = std::fs::File::open("assets/MPEG/Vf9Lvifxwk4.adts").unwrap();
+
+ let mut pkts = super::get_packetiser_adts();
+ file.read_exact(&mut buf).unwrap();
+ pkts.add_data(&buf);
+ let stream = pkts.parse_stream(0).unwrap();
+ let mut frame_sizes = Vec::with_capacity(15);
+ while let Some(pkt) = pkts.get_packet(stream.clone()).unwrap() {
+ let frame_size = pkt.get_buffer().len();
+ println!("pkt size {}", frame_size);
+ frame_sizes.push(frame_size);
+ }
+ assert_eq!(&frame_sizes, &[371, 372, 394, 402, 474, 400, 407, 399, 385]);
+ }
}
const DEFAULT_CHANNEL_MAP: [&str; 9] = [
--- /dev/null
+use nihav_core::codecs::*;
+use nihav_core::io::bitreader::*;
+use super::info::*;
+
+#[derive(Default,Clone,Copy)]
+struct ADTSHeader {
+ srate: u32,
+ channels: u8,
+ hdr_size: usize,
+ frame_size: usize,
+ samples: usize,
+ hdr: u32,
+}
+
+impl PartialEq for ADTSHeader {
+ fn eq(&self, other: &Self) -> bool {
+ self.hdr == other.hdr
+ }
+}
+
+#[derive(Default)]
+struct PacketiserADTS {
+ buf: Vec<u8>,
+ hdr: Option<ADTSHeader>,
+}
+
+impl PacketiserADTS {
+ fn new() -> Self { Self::default() }
+ fn skip_id3(buf: &[u8]) -> DecoderResult<usize> {
+ // check for ID3 tags in concatenated stream fragments
+ if &buf[0..3] == b"ID3" && (1..=4).contains(&buf[3]) && buf[4] == 0 {
+ if buf.len() < 10 {
+ return Err(DecoderError::ShortData);
+ }
+ let mut size = 0;
+ for &b in buf[6..10].iter() {
+ if (b & 0x80) != 0 {
+ return Err(DecoderError::InvalidData);
+ }
+ size = (size << 7) | usize::from(b);
+ }
+ Ok(size + 10)
+ } else {
+ Ok(0)
+ }
+ }
+ fn parse_header(&self, off: usize) -> DecoderResult<ADTSHeader> {
+ if self.buf.len() < off + 7 { return Err(DecoderError::ShortData); }
+
+ let mut br = BitReader::new(&self.buf[off..], BitReaderMode::BE);
+
+ let syncword = br.read(12)?;
+ if syncword != 0xFFF { return Err(DecoderError::InvalidData); }
+ let _id = br.read(1)?;
+ let layer = br.read(2)?;
+ if layer != 0 { return Err(DecoderError::InvalidData); }
+ let protection_absent = br.read_bool()?;
+ let profile = br.read(2)?;
+ validate!(profile != 3);
+ let sf_idx = br.read(4)?;
+ validate!(sf_idx <= 12);
+ let _private_bit = br.read_bool()?;
+ let ch_config = br.read(3)?;
+ validate!(ch_config != 0);
+ let _original = br.read_bool()?;
+ let _home = br.read_bool()?;
+
+ let _copy_id_bit = br.read_bool()?;
+ let _copy_id_start = br.read_bool()?;
+ let frame_length = br.read(13)? as usize;
+ let _buffer_fullness = br.read(11)?;
+ let num_raw_blocks = br.read(2)? as usize;
+
+ let hdr = ((profile + 1) << 27) | (sf_idx << 23) | (ch_config << 19);
+
+ if num_raw_blocks == 0 {
+ if !protection_absent {
+ br.skip(16)?; // CRC
+ }
+ let hdr_size = br.tell() / 8;
+ validate!(frame_length > hdr_size);
+ let frame_size = frame_length - hdr_size;
+
+ Ok(ADTSHeader {
+ srate: AAC_SAMPLE_RATES[sf_idx as usize],
+ channels: AAC_CHANNELS[ch_config as usize] as u8,
+ hdr_size, frame_size, hdr,
+ samples: 1024
+ })
+ } else {
+ Err(DecoderError::NotImplemented)
+ }
+ }
+}
+
+impl NAPacketiser for PacketiserADTS {
+ fn attach_stream(&mut self, _stream: NAStreamRef) {}
+ fn add_data(&mut self, src: &[u8]) -> bool {
+ self.buf.extend_from_slice(src);
+ self.buf.len() < 65536
+ }
+ fn parse_stream(&mut self, id: u32) -> DecoderResult<NAStreamRef> {
+ if self.hdr.is_none() {
+ if self.buf.len() < 7 {
+ return Err(DecoderError::ShortData);
+ }
+ let id3_len = Self::skip_id3(&self.buf)?;
+ if id3_len + 7 > self.buf.len() {
+ return Err(DecoderError::ShortData);
+ }
+ let hdr = self.parse_header(id3_len)?;
+ self.hdr = Some(hdr);
+ }
+ let hdr = self.hdr.unwrap();
+ let ainfo = NAAudioInfo::new(hdr.srate, hdr.channels, SND_F32P_FORMAT, hdr.samples);
+ let edata = vec![(hdr.hdr >> 24) as u8, (hdr.hdr >> 16) as u8];
+ let info = NACodecInfo::new("aac", NACodecTypeInfo::Audio(ainfo), Some(edata));
+ Ok(NAStream::new(StreamType::Audio, id, info, hdr.samples as u32, hdr.srate, 0).into_ref())
+ }
+ fn skip_junk(&mut self) -> DecoderResult<usize> {
+ if self.buf.len() <= 8 {
+ 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();
+ loop {
+ if (hdr & 0xFFF6) == 0xFFF6 {
+ let ret = self.parse_header(off);
+ match ret {
+ Ok(hdr) => {
+ if self.hdr.is_none() {
+ self.hdr = Some(hdr);
+ }
+ if self.hdr.unwrap() != hdr { // 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<Option<NAPacket>> {
+ if self.buf.len() < 8 {
+ return Err(DecoderError::ShortData);
+ }
+
+ let id3_len = Self::skip_id3(&self.buf)?;
+ if id3_len + 8 <= self.buf.len() {
+ self.buf.drain(..id3_len);
+ } else {
+ return Err(DecoderError::ShortData);
+ }
+
+ let hdr = self.parse_header(0)?;
+ if self.hdr.is_none() {
+ self.hdr = Some(hdr);
+ }
+ if self.hdr.unwrap() != hdr {
+ return Err(DecoderError::InvalidData);
+ }
+ if hdr.frame_size + hdr.hdr_size <= self.buf.len() {
+ let mut data = Vec::with_capacity(hdr.frame_size);
+ data.extend_from_slice(&self.buf[hdr.hdr_size..][..hdr.frame_size]);
+ self.buf.drain(..hdr.hdr_size + hdr.frame_size);
+ let ts = NATimeInfo::new(None, None, Some(1), hdr.samples as u32, hdr.srate);
+ 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_adts() -> Box<dyn NAPacketiser + Send> {
+ Box::new(PacketiserADTS::new())
+}