From b43b687dac0360e002e6c6499ccf9381dfc7f38a Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Wed, 28 Oct 2026 22:08:03 +0100 Subject: [PATCH] flac: support full header in extradata --- nihav-llaudio/src/codecs/flac.rs | 53 ++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/nihav-llaudio/src/codecs/flac.rs b/nihav-llaudio/src/codecs/flac.rs index ac6fd53..38613f1 100644 --- a/nihav-llaudio/src/codecs/flac.rs +++ b/nihav-llaudio/src/codecs/flac.rs @@ -149,6 +149,37 @@ impl FlacDecoder { vec![0; MAX_SAMPLES], vec![0; MAX_SAMPLES]], } } + fn parse_flac_header(&mut self, br: &mut dyn ByteIO) -> DecoderResult<()> { + let tag = br.read_tag()?; + validate!(&tag == b"fLaC"); + loop { + let id1 = br.read_byte()?; + let len = br.read_u24be()? as usize; + let id = id1 & 0x7F; + + if id == 0x00 { + validate!(len >= 34); + let mut streaminfo = vec![0u8; len]; + br.read_buf(&mut streaminfo)?; + self.min_blk_size = usize::from(read_u16be(&streaminfo[0..])?); + self.max_blk_size = usize::from(read_u16be(&streaminfo[2..])?); + self.min_frm_size = read_u24be(&streaminfo[4..])? as usize; + self.max_frm_size = read_u24be(&streaminfo[7..])? as usize; + let word = read_u32be(&streaminfo[10..])?; + self.srate = word >> 12; + self.channels = (((word >> 9) & 7) + 1) as u8; + self.bits = (((word >> 4) & 0x1F) + 1) as u8; + return Ok(()); + } else { + br.read_skip(len)?; + } + + if (id1 & 0x80) != 0 { + break; + } + } + Err(DecoderError::InvalidData) + } fn apply_chmod(&mut self, blocksize: usize, chmod: StereoMode) { match chmod { StereoMode::Normal => {}, @@ -245,15 +276,19 @@ impl NADecoder for FlacDecoder { let mut br = MemoryReader::new_read(&buf); - self.min_blk_size = br.read_u16be()? as usize; - self.max_blk_size = br.read_u16be()? as usize; - self.min_frm_size = br.read_u24be()? as usize; - self.max_frm_size = br.read_u24be()? as usize; - let tmp = br.read_u64be()?; - self.srate = (tmp >> 44) as u32; - self.channels = (((tmp >> 41) & 7) + 1) as u8; - self.bits = (((tmp >> 36) & 0x1F) + 1) as u8; - //let tot_samples = tmp & ((1 << 36) - 1); + if &buf[..4] != b"fLaC" { + self.min_blk_size = br.read_u16be()? as usize; + self.max_blk_size = br.read_u16be()? as usize; + self.min_frm_size = br.read_u24be()? as usize; + self.max_frm_size = br.read_u24be()? as usize; + let tmp = br.read_u64be()?; + self.srate = (tmp >> 44) as u32; + self.channels = (((tmp >> 41) & 7) + 1) as u8; + self.bits = (((tmp >> 36) & 0x1F) + 1) as u8; + //let tot_samples = tmp & ((1 << 36) - 1); + } else { + self.parse_flac_header(&mut br)?; + } self.chmap = NAChannelMap::from_str(DEFAULT_CHANNEL_MAPS[(self.channels - 1) as usize]).unwrap(); let fmt = match self.bits { -- 2.47.3