]> git.nihav.org Git - nihav.git/commitdiff
flac: support full header in extradata
authorKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 28 Oct 2026 21:08:03 +0000 (22:08 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 28 Oct 2026 21:08:39 +0000 (22:08 +0100)
nihav-llaudio/src/codecs/flac.rs

index ac6fd5352c0fc93780778b70116e1a88683353e1..38613f1a17bc20bea575a3d95bdcb82a3039a832 100644 (file)
@@ -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 {