remove tabs
[nihav.git] / nihav-llaudio / src / codecs / flac.rs
index 0ca80aab48bcb1d0ca3a12ccf05b60110e657a20..e0b407d68c32fa36e7c90246339d6bd532546783 100644 (file)
@@ -429,13 +429,214 @@ pub fn get_decoder() -> Box<dyn NADecoder + Send> {
     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<u8>,
+    ref_crc:    u16,
+    cur_crc:    u16,
+    end:        usize,
+    hdr_ok:     bool,
+}
+
+fn read_utf8(br: &mut BitReader) -> DecoderResult<u64> {
+    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<FrameHeader> {
+        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<NAStreamRef> {
+        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<usize> {
+        Err(DecoderError::NotImplemented)
+    }
+    fn get_packet(&mut self, stream: NAStreamRef) -> DecoderResult<Option<NAPacket>> {
+        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<dyn NAPacketiser + Send> {
+    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
 ];