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> {
srate: 0,
known_frames: Vec::new(),
build_index: false,
+ frame_hdr: 0,
}
}
fn read_frame(&mut self) -> DemuxerResult<(Vec<u8>, u64, u64)> {
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()?;
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;
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 };
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)
#[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);