use coeff_read::*;
mod info;
use info::*;
+#[allow(clippy::needless_range_loop)]
mod sbr;
use sbr::{SBRHeader, SBRCodebooks, SBRState, SBRChannel, SBRDSP, sbr_read_sce, sbr_read_cpe};
#[allow(clippy::excessive_precision)]
mod tools;
use tools::*;
+mod packetiser;
+pub use packetiser::get_packetiser_adts;
+
const MAX_WINDOWS: usize = 8;
const MAX_SFBS: usize = 64;
fn get_intensity_dir(&self, g: usize, sfb: usize) -> bool {
self.sfb_cb[g][sfb] == INTENSITY_HCB
}
+ fn is_noise(&self, g: usize, sfb: usize) -> bool {
+ self.sfb_cb[g][sfb] == NOISE_HCB
+ }
fn decode_scale_factor_data(&mut self, br: &mut BitReader, codebooks: &Codebooks) -> DecoderResult<()> {
decode_scale_factor_data(br, &mut self.scales, self.global_gain, &self.info, &self.sfb_cb, codebooks)
}
self.ms_used[g][sfb] = br.read_bool()?;
}
}
+ } else {
+ self.ms_used = [[false; MAX_SFBS]; MAX_WINDOWS];
}
self.ics[1].info = self.ics[0].info;
}
self.ics[0].decode_ics(br, codebooks, m4atype, common_window, true)?;
self.ics[1].decode_ics(br, codebooks, m4atype, common_window, true)?;
- if common_window && self.ms_mask_present != 0 {
+ if common_window {
let mut g = 0;
for w in 0..self.ics[0].info.num_windows {
if w > 0 && !self.ics[0].info.scale_factor_grouping[w - 1] {
for sfb in 0..self.ics[0].info.max_sfb {
let start = w * 128 + self.ics[0].get_band_start(sfb);
let end = w * 128 + self.ics[0].get_band_start(sfb + 1);
- if self.ics[0].is_intensity(g, sfb) {
+ if self.ics[1].is_intensity(g, sfb) {
let invert = (self.ms_mask_present == 1) && self.ms_used[g][sfb];
- let dir = self.ics[0].get_intensity_dir(g, sfb) ^ invert;
- let scale = 0.5f32.powf(0.25 * (f32::from(self.ics[0].scales[g][sfb]) + f32::from(INTENSITY_SCALE_MIN)));
- if !dir {
+ let dir = self.ics[1].get_intensity_dir(g, sfb) ^ invert;
+ let scale = 0.5f32.powf(0.25 * (f32::from(self.ics[1].scales[g][sfb]) + f32::from(INTENSITY_SCALE_MIN)));
+ if dir {
for i in start..end {
self.ics[1].coeffs[i] = scale * self.ics[0].coeffs[i];
}
self.ics[1].coeffs[i] = -scale * self.ics[0].coeffs[i];
}
}
- } else if (self.ms_mask_present == 2) || self.ms_used[g][sfb] {
+ } else if ((self.ms_mask_present == 2) || self.ms_used[g][sfb]) && !self.ics[0].is_noise(g, sfb) {
for i in start..end {
let tmp = self.ics[0].coeffs[i] - self.ics[1].coeffs[i];
self.ics[0].coeffs[i] += self.ics[1].coeffs[i];
self.ew_buf[w * 128 + i] += src[i] * short_win[i];
}
} else { // to be left-windowed
- for i in 0..128 {
- self.ew_buf[i] = src[i];
- }
+ self.ew_buf[..128].copy_from_slice(&src[..128]);
}
for i in 0..128 {
self.ew_buf[w * 128 + i + 128] += src[i + 128] * short_win[127 - i];
}
},
EIGHT_SHORT_SEQUENCE => {
- for i in 0..SHORT_WIN_POINT0 {
- dst[i] = delay[i];
- }
+ dst[..SHORT_WIN_POINT0].copy_from_slice(&delay[..SHORT_WIN_POINT0]);
for i in SHORT_WIN_POINT0..SHORT_WIN_POINT1 {
let j = i - SHORT_WIN_POINT0;
dst[i] = delay[i] + self.ew_buf[j] * left_short_win[j];
}
- for i in SHORT_WIN_POINT1..1024 {
- let j = i - SHORT_WIN_POINT0;
- dst[i] = self.ew_buf[j];
- }
+ dst[SHORT_WIN_POINT1..1024].copy_from_slice(
+ &self.ew_buf[SHORT_WIN_POINT1-SHORT_WIN_POINT0..1024-SHORT_WIN_POINT0]);
},
LONG_STOP_SEQUENCE => {
- for i in 0..SHORT_WIN_POINT0 {
- dst[i] = delay[i];
- }
+ dst[..SHORT_WIN_POINT0].copy_from_slice(&delay[..SHORT_WIN_POINT0]);
for i in SHORT_WIN_POINT0..SHORT_WIN_POINT1 {
dst[i] = delay[i] + self.tmp[i] * left_short_win[i - SHORT_WIN_POINT0];
}
- for i in SHORT_WIN_POINT1..1024 {
- dst[i] = self.tmp[i];
- }
+ dst[SHORT_WIN_POINT1..1024].copy_from_slice(&self.tmp[SHORT_WIN_POINT1..1024]);
},
_ => unreachable!(""),
};
// save delay
match seq {
ONLY_LONG_SEQUENCE | LONG_STOP_SEQUENCE => {
- for i in 0..1024 {
- delay[i] = self.tmp[i + 1024] * long_win[1023 - i];
+ for (dst, (&src, &win)) in delay.iter_mut()
+ .zip(self.tmp[1024..].iter().zip(long_win.iter().rev())) {
+ *dst = src * win;
}
},
EIGHT_SHORT_SEQUENCE => {
- for i in 0..SHORT_WIN_POINT1 { // last part is already windowed
- delay[i] = self.ew_buf[i + 512+64];
- }
- for i in SHORT_WIN_POINT1..1024 {
- delay[i] = 0.0;
+ // last part is already windowed
+ delay[..SHORT_WIN_POINT1].copy_from_slice(&self.ew_buf[512+64..][..SHORT_WIN_POINT1]);
+ for el in delay[SHORT_WIN_POINT1..].iter_mut() {
+ *el = 0.0;
}
},
LONG_START_SEQUENCE => {
- for i in 0..SHORT_WIN_POINT0 {
- delay[i] = self.tmp[i + 1024];
- }
+ delay[..SHORT_WIN_POINT0].copy_from_slice(&self.tmp[1024..][..SHORT_WIN_POINT0]);
for i in SHORT_WIN_POINT0..SHORT_WIN_POINT1 {
delay[i] = self.tmp[i + 1024] * short_win[127 - (i - SHORT_WIN_POINT0)];
}
- for i in SHORT_WIN_POINT1..1024 {
- delay[i] = 0.0;
+ for el in delay[SHORT_WIN_POINT1..].iter_mut() {
+ *el = 0.0;
}
},
_ => unreachable!(""),
4 => { // ID_DSE
let _id = br.read(4)?;
let align = br.read_bool()?;
- let mut count = br.read(8)? as u32;
- if count == 255 { count += br.read(8)? as u32; }
+ let mut count = br.read(8)?;
+ if count == 255 { count += br.read(8)?; }
if align { br.align(); }
br.skip(count * 8)?; // no SBR payload or such
},
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] = [