X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-llaudio%2Fsrc%2Fcodecs%2Fflac.rs;h=e0b407d68c32fa36e7c90246339d6bd532546783;hp=55cd6bbacb96081530fca19e8d47e0a4eb22d74d;hb=afede4c7d70ece7152ac00a026e37fff052b117e;hpb=87927c5732b39bb23209486bed8d7bb7fc56b92e diff --git a/nihav-llaudio/src/codecs/flac.rs b/nihav-llaudio/src/codecs/flac.rs index 55cd6bb..e0b407d 100644 --- a/nihav-llaudio/src/codecs/flac.rs +++ b/nihav-llaudio/src/codecs/flac.rs @@ -121,7 +121,7 @@ fn apply_fixed_predictor(dst: &mut [i32], order: usize) { }; } -fn apply_lpc(dst: &mut [i32], filt: &[i32; 16], order: usize, shift: u8) { +fn apply_lpc(dst: &mut [i32], filt: &[i32; 32], order: usize, shift: u8) { for i in order..dst.len() { let mut sum = 0i64; for (coef, filt) in dst[i - order..].iter().take(order).zip(filt.iter()) { @@ -213,7 +213,7 @@ impl FlacDecoder { let precision = br.read(4)? as u8 + 1; validate!(precision < 16); let shift = br.read(5)? as u8; - let mut filter = [0i32; 16]; + let mut filter = [0i32; 32]; for el in filter[..order].iter_mut().rev() { *el = br.read_s(precision)?; } @@ -429,13 +429,214 @@ pub fn get_decoder() -> Box { Box::new(FlacDecoder::new()) } +#[derive(Clone,Copy,Default)] +struct FrameHeader { + blocksize: u32, + srate: u32, + channels: u8, + bits: u8, + time: u64, + blk_strat: bool, +} + +#[derive(Default)] +struct FLACPacketiser { + hdr: FrameHeader, + buf: Vec, + ref_crc: u16, + cur_crc: u16, + end: usize, + hdr_ok: bool, +} + +fn read_utf8(br: &mut BitReader) -> DecoderResult { + let byte = br.read(8)? as u8; + let len = (!byte).leading_zeros(); + if (len == 1) || (len > 5) { + return Err(DecoderError::InvalidData); + } + if len > 1 { + let mut val = u64::from(byte << len >> len); + for _ in 1..len { + let byte = br.read(8)?; + if (byte & 0xC0) != 0x80 { + return Err(DecoderError::InvalidData); + } + val = (val << 6) | u64::from(byte & 0x3F); + } + Ok(val) + } else { + Ok(u64::from(byte)) + } +} + +impl FLACPacketiser { + fn new() -> Self { Self::default() } + fn parse_header(&self) -> DecoderResult { + if self.buf.len() < 5 { + return Err(DecoderError::ShortData); + } + let mut br = BitReader::new(&self.buf, BitReaderMode::BE); + let sync_code = br.read(14)?; + if sync_code != 0x3FFE { + return Err(DecoderError::InvalidData); + } + let marker = br.read(1)?; + if marker != 0 { + return Err(DecoderError::InvalidData); + } + let blk_strat = br.read_bool()?; + let bsize = br.read(4)?; + let srate_idx = br.read(4)? as u8; + let chan_idx = br.read(4)? as u8; + let bits = match br.read(3)? { + 0 => 0, + 1 => 8, + 2 => 12, + 4 => 16, + 5 => 20, + 6 => 24, + _ => return Err(DecoderError::InvalidData), + }; + let marker = br.read(1)?; + if marker != 0 { + return Err(DecoderError::InvalidData); + } + + let time = read_utf8(&mut br)?; + + let blocksize = match bsize { + 1 => 192, + 2..=5 => 576 << (bsize - 2), + 6 => br.read(8)? + 1, + 7 => br.read(16)? + 1, + 8..=15 => 256 << (bsize - 8), + _ => return Err(DecoderError::InvalidData), + }; + let srate = match srate_idx { + 0 => 0, + 1 => 88200, + 2 => 176400, + 3 => 192000, + 4 => 8000, + 5 => 16000, + 6 => 22050, + 7 => 24000, + 8 => 32000, + 9 => 44100, + 10 => 48000, + 11 => 96000, + 12 => br.read(8)? * 1000, + 13 => br.read(16)?, + 14 => br.read(16)? * 10, + _ => return Err(DecoderError::InvalidData), + }; + let channels = match chan_idx { + 0..=7 => chan_idx + 1, + 8 | 9 | 10 => 2, + _ => return Err(DecoderError::InvalidData), + }; + + let hdr_size = br.tell() / 8; + let ref_crc = br.read(8)? as u8; + let mut crc = 0; + for &b in self.buf[..hdr_size].iter() { + crc = update_crc8(crc, b); + } + if crc != ref_crc { + return Err(DecoderError::ChecksumError); + } + + Ok(FrameHeader{ blk_strat, time, srate, channels, bits, blocksize }) + } +} + +impl NAPacketiser for FLACPacketiser { + 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 { + let hdr = self.parse_header()?; + let ainfo = NAAudioInfo::new(hdr.srate, hdr.channels, if hdr.bits <= 16 { SND_S16P_FORMAT } else { SND_S32P_FORMAT }, hdr.blocksize as usize); + let info = NACodecInfo::new("flac", NACodecTypeInfo::Audio(ainfo), None); + Ok(NAStream::new(StreamType::Audio, id, info, 1, hdr.srate, 0).into_ref()) + } + fn skip_junk(&mut self) -> DecoderResult { + Err(DecoderError::NotImplemented) + } + fn get_packet(&mut self, stream: NAStreamRef) -> DecoderResult> { + if self.end == self.buf.len() || self.buf.len() < 5 { + return Err(DecoderError::ShortData); + } + if !self.hdr_ok { + self.hdr = self.parse_header()?; + self.hdr_ok = true; + self.cur_crc = 0; + for i in 0..5 { + self.cur_crc = update_crc16(self.cur_crc, self.buf[i]); + } + self.end = 5; + } + while self.end < self.buf.len() { + let b = self.buf[self.end]; + self.end += 1; + match self.end { + 0..=5 => unreachable!(), + 6 => self.ref_crc = u16::from(b), + 7 => self.ref_crc = (self.ref_crc << 8) | u16::from(b), + _ => { + let bbb = (self.ref_crc >> 8) as u8; + self.ref_crc = (self.ref_crc << 8) | u16::from(b); + self.cur_crc = update_crc16(self.cur_crc, bbb); + let mut found = self.ref_crc == self.cur_crc; + if self.end + 2 < self.buf.len() { + let b1 = self.buf[self.end]; + let b2 = self.buf[self.end + 1]; + if b1 != 0xFF || (b2 & 0xFC) != 0xF8 { + found = false; + } + } + if found { + let mut data = Vec::with_capacity(self.end); + data.extend_from_slice(&self.buf[..self.end]); + self.buf.drain(..self.end); + let mut ts = NATimeInfo::new(None, None, Some(u64::from(self.hdr.blocksize)), 1, self.hdr.srate); + ts.pts = if self.hdr.blk_strat { + Some(self.hdr.time) + } else { + Some(self.hdr.time * u64::from(self.hdr.blocksize)) + }; + self.end = 0; + self.hdr_ok = false; + + return Ok(Some(NAPacket::new(stream, ts, true, data))); + } + }, + } + } + Ok(None) + } + fn reset(&mut self) { + self.buf.clear(); + self.end = 0; + self.hdr_ok = false; + } + fn bytes_left(&self) -> usize { self.buf.len() } +} + +pub fn get_packetiser() -> Box { + Box::new(FLACPacketiser::new()) +} + #[cfg(test)] mod test { - use nihav_core::codecs::RegisteredDecoders; - use nihav_core::demuxers::RegisteredDemuxers; + use nihav_core::codecs::*; + use nihav_core::demuxers::*; use nihav_codec_support::test::dec_video::*; use crate::llaudio_register_all_decoders; use crate::llaudio_register_all_demuxers; + // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.flac #[test] fn test_flac() { let mut dmx_reg = RegisteredDemuxers::new(); @@ -446,6 +647,90 @@ mod test { test_decoding("flac", "flac", "assets/LLaudio/luckynight.flac", Some(6), &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0xe689787a, 0x032a98f7, 0xeb6e64f4, 0xfa652132])); } + use std::io::{Read, Seek, SeekFrom}; + #[test] + fn test_flac_packetiser() { + let mut dmx_reg = RegisteredDemuxers::new(); + llaudio_register_all_demuxers(&mut dmx_reg); + let dmx_f = dmx_reg.find_demuxer("flac").unwrap(); + let mut file = std::fs::File::open("assets/LLaudio/luckynight.flac").unwrap(); + let mut fr = FileReader::new_read(&mut file); + let mut br = ByteReader::new(&mut fr); + let mut dmx = create_demuxer(dmx_f, &mut br).unwrap(); + + let mut pkt_sizes = Vec::new(); + while let Ok(pkt) = dmx.get_frame() { + pkt_sizes.push(pkt.get_buffer().len()); + } + + let mut file = std::fs::File::open("assets/LLaudio/luckynight.flac").unwrap(); + file.seek(SeekFrom::Start(0x115E)).unwrap(); + + let mut pkts = super::FLACPacketiser::new(); + let mut buf = [0; 8192]; + for _ in 0..16 { + file.read_exact(&mut buf).unwrap(); + pkts.add_data(&buf); + } + let stream = pkts.parse_stream(0).unwrap(); + let mut pkt_sizes2 = Vec::new(); + let mut piter = pkt_sizes.iter(); + loop { + let res = pkts.get_packet(stream.clone()); + match res { + Ok(Some(pkt)) => { + assert_eq!(*piter.next().unwrap(), pkt.get_buffer().len()); + pkt_sizes2.push(pkt.get_buffer().len()); + continue; + }, + Ok(None) | Err(DecoderError::ShortData) => {}, + Err(err) => { + println!("error {:?}", err); + panic!("packetising error"); + }, + }; + let ret = file.read(&mut buf); + match ret { + Ok(0) => { + let res = pkts.get_packet(stream.clone()); + match res { + Ok(Some(pkt)) => { + assert_eq!(*piter.next().unwrap(), pkt.get_buffer().len()); + pkt_sizes2.push(pkt.get_buffer().len()); + continue; + }, + Ok(None) | Err(DecoderError::ShortData) => break, + Err(err) => { + println!("error {:?}", err); + panic!("packetising error"); + }, + }; + }, + Ok(size) => pkts.add_data(&buf[..size]), + Err(err) => { + if err.kind() == std::io::ErrorKind::UnexpectedEof { + let res = pkts.get_packet(stream.clone()); + match res { + Ok(Some(pkt)) => { + assert_eq!(*piter.next().unwrap(), pkt.get_buffer().len()); + pkt_sizes2.push(pkt.get_buffer().len()); + continue; + }, + Ok(None) | Err(DecoderError::ShortData) => break, + Err(err) => { + println!("error {:?}", err); + panic!("packetising error"); + }, + }; + } else { + println!(" {:?}", err.kind()); + panic!("i/o error!"); + } + }, + }; + } + assert_eq!(pkt_sizes.len(), pkt_sizes2.len()); + } } fn update_crc8(crc: u8, byte: u8) -> u8 { @@ -458,36 +743,36 @@ fn update_crc16(crc: u16, byte: u8) -> u16 { const CRC8_TABLE: [u8; 256] = [ 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, - 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, - 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, - 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, - 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, - 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, - 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, - 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, - 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, - 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, - 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, - 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, - 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, - 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, - 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, - 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, - 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, - 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, - 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, - 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, - 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, - 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, - 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, - 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, - 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, - 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, - 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, - 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, - 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, - 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, - 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, + 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, + 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, + 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, + 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, + 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, + 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, + 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, + 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, + 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, + 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, + 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, + 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, + 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, + 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, + 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, + 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, + 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, + 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, + 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 ];