| 1 | use nihav_core::frame::*; |
| 2 | use nihav_core::demuxers::*; |
| 3 | |
| 4 | #[derive(Clone,Copy)] |
| 5 | struct Frame { |
| 6 | off: u32, |
| 7 | size: u32, |
| 8 | bits_off: u8, |
| 9 | } |
| 10 | |
| 11 | struct APEDemuxer<'a> { |
| 12 | src: &'a mut ByteReader<'a>, |
| 13 | cur_frame: usize, |
| 14 | frames: Vec<Frame>, |
| 15 | normal_blocks: u32, |
| 16 | last_blocks: u32, |
| 17 | truncated: bool, |
| 18 | duration: u64, |
| 19 | } |
| 20 | |
| 21 | impl<'a> APEDemuxer<'a> { |
| 22 | fn new(io: &'a mut ByteReader<'a>) -> Self { |
| 23 | Self { |
| 24 | src: io, |
| 25 | cur_frame: 0, |
| 26 | frames: Vec::new(), |
| 27 | normal_blocks: 0, |
| 28 | last_blocks: 0, |
| 29 | truncated: false, |
| 30 | duration: 0, |
| 31 | } |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | impl<'a> DemuxCore<'a> for APEDemuxer<'a> { |
| 36 | fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> { |
| 37 | let src = &mut self.src; |
| 38 | |
| 39 | let tag = src.read_tag()?; |
| 40 | validate!(&tag == b"MAC "); |
| 41 | let version = src.read_u16le()?; |
| 42 | validate!(version >= 3800 && version <= 3990); |
| 43 | |
| 44 | let seektab_len; |
| 45 | let _wavtail_len; |
| 46 | let compr_type; |
| 47 | let flags; |
| 48 | let blocksperframe; |
| 49 | let finalblocks; |
| 50 | let nframes; |
| 51 | let bits; |
| 52 | let channels; |
| 53 | let srate; |
| 54 | if version >= 3980 { |
| 55 | src.read_skip(2)?; |
| 56 | let descriptor_len = src.read_u32le()? as usize; |
| 57 | let header_len = src.read_u32le()? as usize; |
| 58 | validate!(header_len == 24); |
| 59 | seektab_len = src.read_u32le()? as usize; |
| 60 | let _wavheader_len = src.read_u32le()? as usize; |
| 61 | let _audio_len = src.read_u64le()?; |
| 62 | _wavtail_len = src.read_u32le()? as usize; |
| 63 | src.read_skip(16)?; // unpacked data MD5 |
| 64 | if descriptor_len > 52 { |
| 65 | src.read_skip(descriptor_len - 52)?; |
| 66 | } |
| 67 | |
| 68 | compr_type = src.read_u16le()?; |
| 69 | flags = src.read_u16le()?; |
| 70 | blocksperframe = src.read_u32le()?; |
| 71 | finalblocks = src.read_u32le()?; |
| 72 | nframes = src.read_u32le()? as usize; |
| 73 | bits = src.read_u16le()?; |
| 74 | channels = src.read_u16le()?; |
| 75 | srate = src.read_u32le()?; |
| 76 | } else { |
| 77 | compr_type = src.read_u16le()?; |
| 78 | flags = src.read_u16le()?; |
| 79 | channels = src.read_u16le()?; |
| 80 | srate = src.read_u32le()?; |
| 81 | |
| 82 | let wavheader_len = src.read_u32le()? as usize; |
| 83 | _wavtail_len = src.read_u32le()? as usize; |
| 84 | nframes = src.read_u32le()? as usize; |
| 85 | finalblocks = src.read_u32le()?; |
| 86 | if (flags & 0x04) != 0 { |
| 87 | src.read_u32le()?; // peak level |
| 88 | } |
| 89 | if (flags & 0x10) != 0 { |
| 90 | seektab_len = src.read_u32le()? as usize * 4; |
| 91 | } else { |
| 92 | seektab_len = nframes * 4; |
| 93 | } |
| 94 | |
| 95 | if (flags & 0x01) != 0 { |
| 96 | bits = 8; |
| 97 | } else if (flags & 0x08) != 0 { |
| 98 | bits = 24; |
| 99 | } else { |
| 100 | bits = 16; |
| 101 | } |
| 102 | |
| 103 | blocksperframe = 9216 * if version >= 3950 { |
| 104 | 32 |
| 105 | } else if (version >= 3900) || ((version >= 3800) && (compr_type >= 4000)) { |
| 106 | 8 |
| 107 | } else { |
| 108 | 1 |
| 109 | }; |
| 110 | |
| 111 | if (flags & 0x20) == 0 { |
| 112 | src.read_skip(wavheader_len)?; |
| 113 | } |
| 114 | } |
| 115 | validate!(srate > 0); |
| 116 | validate!(channels > 0 && channels < 256); |
| 117 | validate!(bits > 0 && bits <= 32); |
| 118 | validate!(nframes > 0 && nframes < (1 << 28)); |
| 119 | validate!(seektab_len >= nframes * 4); |
| 120 | |
| 121 | self.frames = Vec::with_capacity(nframes); |
| 122 | self.normal_blocks = blocksperframe; |
| 123 | self.last_blocks = finalblocks; |
| 124 | self.duration = (((nframes - 1) as u64) * u64::from(blocksperframe) + u64::from(finalblocks)) * 1000 / u64::from(srate); |
| 125 | |
| 126 | seek_index.mode = SeekIndexMode::Present; |
| 127 | let first_off = src.peek_u32le()?; |
| 128 | validate!(u64::from(first_off) >= src.tell() + ((nframes * 4) as u64)); |
| 129 | let mut last_off = first_off - 1; |
| 130 | for i in 0..nframes { |
| 131 | let off = src.read_u32le()?; |
| 132 | validate!(off > last_off); |
| 133 | let diff = (off - first_off) & 3; |
| 134 | self.frames.push(Frame { |
| 135 | off: off - diff, |
| 136 | size: 0, |
| 137 | bits_off: (diff as u8) * 8, |
| 138 | }); |
| 139 | |
| 140 | last_off = off; |
| 141 | |
| 142 | let time = (i as u64) * u64::from(blocksperframe) * 1000 / u64::from(srate); |
| 143 | seek_index.add_entry(0, SeekEntry { time, pts: i as u64, pos: i as u64 }); |
| 144 | } |
| 145 | if version < 3810 { |
| 146 | for frame in self.frames.iter_mut() { |
| 147 | let bits = src.read_byte()?; |
| 148 | validate!(bits < 32); |
| 149 | frame.bits_off += bits; |
| 150 | } |
| 151 | } |
| 152 | src.seek(SeekFrom::End(0))?; |
| 153 | let fsize = src.tell(); |
| 154 | validate!(fsize > u64::from(self.frames[0].off)); |
| 155 | self.truncated = u64::from(self.frames[self.frames.len() - 1].off) >= fsize; |
| 156 | if self.truncated { |
| 157 | let mut valid_frames = self.frames.len(); |
| 158 | for frame in self.frames.iter_mut().rev() { |
| 159 | if u64::from(frame.off) >= fsize { |
| 160 | valid_frames -= 1; |
| 161 | } |
| 162 | } |
| 163 | self.frames.truncate(valid_frames); |
| 164 | validate!(!self.frames.is_empty()); |
| 165 | self.truncated = true; |
| 166 | } |
| 167 | let mut last_off = fsize as u32; |
| 168 | for frame in self.frames.iter_mut().rev() { |
| 169 | frame.size = last_off - frame.off; |
| 170 | last_off = frame.off + (if frame.bits_off > 0 { 4 } else { 0 }); |
| 171 | } |
| 172 | |
| 173 | let mut hdr = vec![0u8; 16]; |
| 174 | write_u16le(&mut hdr[0..], version)?; |
| 175 | write_u16le(&mut hdr[2..], compr_type)?; |
| 176 | write_u16le(&mut hdr[4..], flags)?; |
| 177 | hdr[6] = channels as u8; |
| 178 | hdr[7] = bits as u8; |
| 179 | write_u32le(&mut hdr[8..], srate)?; |
| 180 | write_u32le(&mut hdr[12..], blocksperframe)?; |
| 181 | |
| 182 | let ahdr = NAAudioInfo::new(srate, channels as u8, SND_S16P_FORMAT, 1); |
| 183 | let ainfo = NACodecInfo::new("ape", NACodecTypeInfo::Audio(ahdr), Some(hdr)); |
| 184 | strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, blocksperframe, srate, nframes as u64)).unwrap(); |
| 185 | |
| 186 | self.cur_frame = 0; |
| 187 | |
| 188 | Ok(()) |
| 189 | } |
| 190 | fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> { |
| 191 | if self.cur_frame >= self.frames.len() { |
| 192 | return Err(DemuxerError::EOF); |
| 193 | } |
| 194 | |
| 195 | let size = self.frames[self.cur_frame].size as usize; |
| 196 | let off = self.frames[self.cur_frame].off; |
| 197 | let bits = self.frames[self.cur_frame].bits_off; |
| 198 | let nblocks = if (self.cur_frame < self.frames.len() - 1) || self.truncated { self.normal_blocks } else { self.last_blocks }; |
| 199 | |
| 200 | self.src.seek(SeekFrom::Start(off.into()))?; |
| 201 | |
| 202 | let mut buf = vec![0u8; size + 8]; |
| 203 | write_u32le(&mut buf[0..], nblocks)?; |
| 204 | buf[4] = bits; |
| 205 | self.src.read_buf(&mut buf[8..])?; |
| 206 | |
| 207 | let stream = strmgr.get_stream(0).unwrap(); |
| 208 | let (tb_num, tb_den) = stream.get_timebase(); |
| 209 | let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, tb_num, tb_den); |
| 210 | let pkt = NAPacket::new(stream, ts, true, buf); |
| 211 | |
| 212 | self.cur_frame += 1; |
| 213 | |
| 214 | Ok(pkt) |
| 215 | } |
| 216 | fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> { |
| 217 | let ret = seek_index.find_pos(time); |
| 218 | if ret.is_none() { |
| 219 | return Err(DemuxerError::SeekError); |
| 220 | } |
| 221 | let seek_info = ret.unwrap(); |
| 222 | self.cur_frame = seek_info.pts as usize; |
| 223 | if self.cur_frame >= self.frames.len() { |
| 224 | return Err(DemuxerError::SeekError); |
| 225 | } |
| 226 | |
| 227 | Ok(()) |
| 228 | } |
| 229 | fn get_duration(&self) -> u64 { self.duration } |
| 230 | } |
| 231 | |
| 232 | impl<'a> NAOptionHandler for APEDemuxer<'a> { |
| 233 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } |
| 234 | fn set_options(&mut self, _options: &[NAOption]) { } |
| 235 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } |
| 236 | } |
| 237 | |
| 238 | pub struct APEDemuxerCreator { } |
| 239 | |
| 240 | impl DemuxerCreator for APEDemuxerCreator { |
| 241 | fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> { |
| 242 | Box::new(APEDemuxer::new(br)) |
| 243 | } |
| 244 | fn get_name(&self) -> &'static str { "ape" } |
| 245 | } |
| 246 | |
| 247 | #[cfg(test)] |
| 248 | mod test { |
| 249 | use super::*; |
| 250 | use std::fs::File; |
| 251 | |
| 252 | #[test] |
| 253 | fn test_ape_demux() { |
| 254 | // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.ape |
| 255 | let mut file = File::open("assets/LLaudio/ape/luckynight.ape").unwrap(); |
| 256 | let mut fr = FileReader::new_read(&mut file); |
| 257 | let mut br = ByteReader::new(&mut fr); |
| 258 | let mut dmx = APEDemuxer::new(&mut br); |
| 259 | let mut sm = StreamManager::new(); |
| 260 | let mut si = SeekIndex::new(); |
| 261 | dmx.open(&mut sm, &mut si).unwrap(); |
| 262 | loop { |
| 263 | let pktres = dmx.get_frame(&mut sm); |
| 264 | if let Err(e) = pktres { |
| 265 | if (e as i32) == (DemuxerError::EOF as i32) { break; } |
| 266 | panic!("error"); |
| 267 | } |
| 268 | let pkt = pktres.unwrap(); |
| 269 | println!("Got {}", pkt); |
| 270 | } |
| 271 | } |
| 272 | } |