fix clippy warnings
[nihav.git] / nihav-llaudio / src / demuxers / flac.rs
index 3d6bca2c49b74ca7967d78b5feda444a9072c2d2..4fb6c4c144b45b4125fb4ca004e3d1d8bec8f328 100644 (file)
@@ -21,6 +21,17 @@ struct FLACDemuxer<'a> {
     srate:          u32,
     known_frames:   Vec<FrameSeekInfo>,
     build_index:    bool,
+    frame_hdr:      u32,
+}
+
+fn common_header_word(mut val: u32) -> u32 {
+    val &= !0x1F000; // blocking strategy and block size
+    let ch_map = (val >> 4) & 0xF;
+    if matches!(ch_map, 0x1 | 0x8 | 0x9 | 0xA) { // stereo coding modes
+        val &= !0xF0;
+        val |= 0x10;
+    }
+    val
 }
 
 impl<'a> FLACDemuxer<'a> {
@@ -37,6 +48,7 @@ impl<'a> FLACDemuxer<'a> {
             srate:          0,
             known_frames:   Vec::new(),
             build_index:    false,
+            frame_hdr:      0,
         }
     }
     fn read_frame(&mut self) -> DemuxerResult<(Vec<u8>, u64, u64)> {
@@ -49,6 +61,9 @@ impl<'a> FLACDemuxer<'a> {
             buf.push(byte);
             crc = update_crc16(crc, byte);
         }
+        if self.frame_hdr == 0 {
+            self.frame_hdr = read_u32be(&buf).unwrap_or(0);
+        }
         let mut ref_crc                 = self.src.read_u16be()?;
         loop {
             let byte                    = self.src.read_byte()?;
@@ -56,9 +71,9 @@ impl<'a> FLACDemuxer<'a> {
             buf.push(old_byte);
             ref_crc = (ref_crc << 8) | u16::from(byte);
             crc = update_crc16(crc, old_byte);
-            if buf.len() + 2 >= self.min_size && crc == ref_crc {
-                let ret                 = self.src.peek_u16be();
-                if ret.is_err() || ((ret.unwrap_or(0) & 0xFFFE) == 0xFFF8) {
+            if buf.len() + 4 >= self.min_size && crc == ref_crc {
+                let ret                 = self.src.peek_u32be();
+                if ret.is_err() || (common_header_word(ret.unwrap_or(0)) == common_header_word(self.frame_hdr)) {
                     buf.push((ref_crc >> 8) as u8);
                     buf.push(ref_crc as u8);
                     break;
@@ -78,9 +93,31 @@ impl<'a> FLACDemuxer<'a> {
                 self.cur_samples = blkno * u64::from(self.blk_samples);
                 (u64::from(self.blk_samples), blkno)
             } else {
-                validate!((buf[1] & 1) != 0);
-                let blksamps = u64::from(read_utf8(&buf[4..])?);
-                (blksamps, self.cur_samples)
+                let mut idx = 5;
+                while idx < buf.len() && (buf[idx] & 0x80) != 0 {
+                    idx += 1;
+                }
+
+                let bsz_id = buf[2] >> 4;
+                let blksamps = match bsz_id {
+                        0 => return Err(DemuxerError::InvalidData),
+                        1 => 192,
+                        2..=5 => 576 << (bsz_id - 2),
+                        6 => {
+                            validate!(idx < buf.len());
+                            u64::from(buf[idx]) + 1
+                        },
+                        7 => {
+                            validate!(idx + 2 <= buf.len());
+                            u64::from(buf[idx]) * 256 + u64::from(buf[idx + 1]) + 1
+                        },
+                        _ => 256 << (bsz_id - 8),
+                    };
+                let pts = u64::from(read_utf8(&buf[4..])?);
+
+                validate!(idx < buf.len());
+
+                (blksamps, pts)
             };
 
         let spos = if self.blk_samples != 0 { pts * u64::from(self.blk_samples) } else { pts };
@@ -175,9 +212,9 @@ impl<'a> DemuxCore<'a> for FLACDemuxer<'a> {
         self.srate = srate;
 
         let base = if self.blk_samples != 0 { u32::from(self.blk_samples) } else { 1 };
-        let ahdr = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, base as usize);
+        let ahdr = NAAudioInfo::new(srate, channels, SND_S16P_FORMAT, base as usize);
         let ainfo = NACodecInfo::new("flac", NACodecTypeInfo::Audio(ahdr), Some(streaminfo));
-        strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, base, srate)).unwrap();
+        strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, base, srate, 0)).unwrap();
 
         Ok(())
     }
@@ -185,8 +222,7 @@ impl<'a> DemuxCore<'a> for FLACDemuxer<'a> {
         let (buf, pts, duration) = self.read_frame()?;
 
         let stream = strmgr.get_stream(0).unwrap();
-        let (tb_num, tb_den) = stream.get_timebase();
-        let ts = NATimeInfo::new(Some(pts), None, Some(duration), tb_num, tb_den);
+        let ts = stream.make_ts(Some(pts), None, Some(duration));
         let pkt = NAPacket::new(stream, ts, true, buf);
 
         Ok(pkt)
@@ -202,7 +238,7 @@ impl<'a> DemuxCore<'a> for FLACDemuxer<'a> {
             self.src.seek(SeekFrom::Start(self.data_start + seek_info.pos))?;
             Ok(())
         } else if let NATimePoint::Milliseconds(ms) = time {
-            let samppos = NATimeInfo::time_to_ts(ms, 1000, self.srate, 1);
+            let samppos = NATimeInfo::time_to_ts(ms, 1000, 1, self.srate);
             if self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).sampleend >= samppos {
                 for point in self.known_frames.iter().rev() {
                     if point.samplepos <= samppos {
@@ -239,6 +275,7 @@ impl<'a> DemuxCore<'a> for FLACDemuxer<'a> {
             Err(DemuxerError::NotPossible)
         }
     }
+    fn get_duration(&self) -> u64 { self.tot_samples * 1000 / u64::from(self.srate) }
 }
 
 impl<'a> NAOptionHandler for FLACDemuxer<'a> {
@@ -263,6 +300,7 @@ mod test {
 
     #[test]
     fn test_flac_demux() {
+        // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.flac
         let mut file = File::open("assets/LLaudio/luckynight.flac").unwrap();
         let mut fr = FileReader::new_read(&mut file);
         let mut br = ByteReader::new(&mut fr);