| 1 | use nihav_core::codecs::*; |
| 2 | use nihav_core::io::byteio::read_u32be; |
| 3 | use nihav_core::io::bitreader::*; |
| 4 | use nihav_codec_support::dsp::qmf::QMF; |
| 5 | |
| 6 | mod mp2data; |
| 7 | mod mp2code; |
| 8 | use mp2code::*; |
| 9 | mod mp3data; |
| 10 | mod mp3code; |
| 11 | use mp3code::*; |
| 12 | |
| 13 | const SAMPLES: usize = 1152; |
| 14 | const BYTEBUF_SIZE: usize = 2048; |
| 15 | |
| 16 | #[allow(clippy::large_enum_variant)] |
| 17 | enum LayerData { |
| 18 | MP1, |
| 19 | MP2(MP2Data), |
| 20 | MP3(MP3Data), |
| 21 | } |
| 22 | |
| 23 | impl LayerData { |
| 24 | fn layer_id(&self) -> u8 { |
| 25 | match *self { |
| 26 | LayerData::MP1 => 0, |
| 27 | LayerData::MP2(_) => 1, |
| 28 | LayerData::MP3(_) => 2, |
| 29 | } |
| 30 | } |
| 31 | fn reset(&mut self) { |
| 32 | match self { |
| 33 | LayerData::MP1 => {}, |
| 34 | LayerData::MP2(ref mut data) => data.reset(), |
| 35 | LayerData::MP3(ref mut data) => data.reset(), |
| 36 | }; |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | struct MPADecoder { |
| 41 | info: NACodecInfoRef, |
| 42 | smap: NAChannelMap, |
| 43 | mmap: NAChannelMap, |
| 44 | qmf: [QMF; 2], |
| 45 | srate: u32, |
| 46 | channels: u8, |
| 47 | sf_idx: usize, |
| 48 | |
| 49 | bytebuf: Vec<u8>, |
| 50 | coeffs: [[f32; SAMPLES]; 2], |
| 51 | out: [[[f32; 32]; 36]; 2], |
| 52 | ctx: LayerData, |
| 53 | } |
| 54 | |
| 55 | impl MPADecoder { |
| 56 | fn new(layer: u8) -> Self { |
| 57 | let ctx = match layer { |
| 58 | 0 => LayerData::MP1, |
| 59 | 1 => LayerData::MP2(MP2Data::new()), |
| 60 | 2 => LayerData::MP3(MP3Data::new()), |
| 61 | _ => unreachable!(), |
| 62 | }; |
| 63 | Self { |
| 64 | info: NACodecInfo::new_dummy(), |
| 65 | smap: NAChannelMap::from_ms_mapping(3), |
| 66 | mmap: NAChannelMap::from_ms_mapping(4), |
| 67 | qmf: [QMF::new(), QMF::new()], |
| 68 | srate: 0, |
| 69 | channels: 0, |
| 70 | sf_idx: 0, |
| 71 | ctx, |
| 72 | |
| 73 | bytebuf: Vec::with_capacity(BYTEBUF_SIZE), |
| 74 | coeffs: [[0.0; SAMPLES]; 2], |
| 75 | out: [[[0.0; 32]; 36]; 2], |
| 76 | } |
| 77 | } |
| 78 | fn read_mp3_side_data(&mut self, br: &mut BitReader, src: &[u8], mono: bool) -> DecoderResult<()> { |
| 79 | if let LayerData::MP3(ref mut ctx) = self.ctx { |
| 80 | let channels = if mono { 1 } else { 2 }; |
| 81 | ctx.mpeg1 = self.sf_idx < 3; |
| 82 | ctx.sf_idx = self.sf_idx; |
| 83 | ctx.read_mp3_side_data(br, channels)?; |
| 84 | let hdr_size = (br.tell() / 8) as usize; |
| 85 | let add_len = src.len() - hdr_size; |
| 86 | if self.bytebuf.len() + add_len > BYTEBUF_SIZE { |
| 87 | self.bytebuf.drain(..self.bytebuf.len() + add_len - BYTEBUF_SIZE); |
| 88 | } |
| 89 | let underrun = self.bytebuf.len() < ctx.main_data_end; |
| 90 | let del_len = if !underrun { self.bytebuf.len() - ctx.main_data_end } else { 0 }; |
| 91 | self.bytebuf.extend_from_slice(&src[hdr_size..]); |
| 92 | self.bytebuf.drain(..del_len); |
| 93 | if underrun { |
| 94 | return Err(DecoderError::MissingReference); |
| 95 | } |
| 96 | |
| 97 | Ok(()) |
| 98 | } else { |
| 99 | Err(DecoderError::Bug) |
| 100 | } |
| 101 | } |
| 102 | fn decode_layer3(&mut self, channels: usize, mode_ext: u8) -> DecoderResult<bool> { |
| 103 | if let LayerData::MP3(ref mut ctx) = self.ctx { |
| 104 | let mut br = BitReader::new(&self.bytebuf, BitReaderMode::BE); |
| 105 | if ctx.mpeg1 { |
| 106 | ctx.decode_mpeg1_layer3(&mut br, &mut self.coeffs, channels)?; |
| 107 | } else { |
| 108 | ctx.decode_mpeg2_layer3(&mut br, &mut self.coeffs, channels, mode_ext)?; |
| 109 | } |
| 110 | let used_data = (br.tell() + 7) / 8; |
| 111 | self.bytebuf.drain(..used_data); |
| 112 | |
| 113 | Ok(true) |
| 114 | } else { |
| 115 | Err(DecoderError::Bug) |
| 116 | } |
| 117 | } |
| 118 | fn synth_layer3(&mut self, mode: u8, mode_ext: u8) { |
| 119 | if let LayerData::MP3(ref mut ctx) = self.ctx { |
| 120 | ctx.synth(&mut self.coeffs, &mut self.out, mode, mode_ext); |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | fn apply_ms(ch0: &mut [f32], ch1: &mut [f32]) { |
| 126 | for (l, r) in ch0.iter_mut().zip(ch1) { |
| 127 | let ll = (*l + *r) * std::f32::consts::FRAC_1_SQRT_2; |
| 128 | let rr = (*l - *r) * std::f32::consts::FRAC_1_SQRT_2; |
| 129 | *l = ll; |
| 130 | *r = rr; |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | impl NADecoder for MPADecoder { |
| 135 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
| 136 | if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { |
| 137 | self.info = info.clone(); |
| 138 | Ok(()) |
| 139 | } else { |
| 140 | Err(DecoderError::InvalidData) |
| 141 | } |
| 142 | } |
| 143 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
| 144 | let info = pkt.get_stream().get_info(); |
| 145 | if let NACodecTypeInfo::Audio(_) = info.get_properties() { |
| 146 | let src = pkt.get_buffer(); |
| 147 | |
| 148 | let mut br = BitReader::new(src.as_slice(), BitReaderMode::BE); |
| 149 | |
| 150 | let syncword = br.read(11)?; |
| 151 | validate!(syncword == 0x7FF); |
| 152 | let id = br.read(2)?; |
| 153 | validate!(id != 1); |
| 154 | let layer = (br.read(2)? ^ 3) as u8; |
| 155 | validate!(layer != 3); |
| 156 | let protection = br.read_bool()?; |
| 157 | let bitrate_index = br.read(4)? as usize; |
| 158 | validate!(bitrate_index < 15); |
| 159 | if bitrate_index == 0 { |
| 160 | //todo freeform eventually |
| 161 | unimplemented!(); |
| 162 | } |
| 163 | let mut sf_idx = br.read(2)? as usize; |
| 164 | validate!(sf_idx != 3); |
| 165 | let padding = br.read_bool()?; |
| 166 | let _private = br.read_bool()?; |
| 167 | let mode = br.read(2)? as u8; |
| 168 | let mode_extension = br.read(2)? as u8; |
| 169 | let _copyright = br.read_bool()?; |
| 170 | let _original = br.read_bool()?; |
| 171 | let _emphasis = br.read(2)?; |
| 172 | if !protection { |
| 173 | let _crc_check = br.read(16)?; |
| 174 | } |
| 175 | validate!(layer == self.ctx.layer_id()); |
| 176 | match id { |
| 177 | 0 => sf_idx += 6, |
| 178 | 2 => sf_idx += 3, |
| 179 | _ => {}, |
| 180 | }; |
| 181 | let mpeg1 = id == 3; |
| 182 | let srate = SAMPLING_RATE[sf_idx]; |
| 183 | if self.srate == 0 { |
| 184 | self.srate = srate; |
| 185 | } |
| 186 | validate!(srate == self.srate); |
| 187 | let channels = if mode == 3 { 1 } else { 2 }; |
| 188 | if self.channels == 0 { |
| 189 | self.channels = channels; |
| 190 | } |
| 191 | if channels != self.channels { |
| 192 | self.flush(); |
| 193 | } |
| 194 | let bitrate = BITRATE[if mpeg1 { 0 } else { 1 }][layer as usize][bitrate_index]; |
| 195 | let frame_size = match layer { |
| 196 | 0 => { |
| 197 | ((SAMPLES / 3 / 8 * 1000 * (bitrate as usize) / (srate as usize)) & !3) + if padding { 4 } else { 0 } |
| 198 | }, |
| 199 | 2 if !mpeg1 => { |
| 200 | SAMPLES / 2 / 8 * 1000 * (bitrate as usize) / (srate as usize) + if padding { 1 } else { 0 } |
| 201 | }, |
| 202 | _ => { |
| 203 | SAMPLES / 8 * 1000 * (bitrate as usize) / (srate as usize) + if padding { 1 } else { 0 } |
| 204 | }, |
| 205 | }; |
| 206 | validate!(src.len() >= frame_size); |
| 207 | self.sf_idx = sf_idx; |
| 208 | |
| 209 | let nsamples = if mpeg1 { SAMPLES } else { SAMPLES / 2 }; |
| 210 | |
| 211 | let ainfo = NAAudioInfo::new(srate, channels, SND_F32P_FORMAT, nsamples); |
| 212 | let chmap = if channels == 1 { self.mmap.clone() } else { self.smap.clone() }; |
| 213 | |
| 214 | let mut abuf = alloc_audio_buffer(ainfo, nsamples, chmap)?; |
| 215 | let mut adata = abuf.get_abuf_f32().unwrap(); |
| 216 | let off = if channels == 1 { adata.get_length() } else { adata.get_stride() }; |
| 217 | let buf = adata.get_data_mut().unwrap(); |
| 218 | let (ch0, ch1) = buf.split_at_mut(off); |
| 219 | |
| 220 | match layer { |
| 221 | 0 => unimplemented!(), |
| 222 | 1 => { |
| 223 | if let LayerData::MP2(ref mut ctx) = self.ctx { |
| 224 | ctx.mpeg1 = self.sf_idx < 3; |
| 225 | ctx.sf_idx = self.sf_idx; |
| 226 | ctx.br_idx = bitrate_index; |
| 227 | ctx.read_layer2(&mut br, channels as usize, &mut self.out, mode, mode_extension)?; |
| 228 | } else { |
| 229 | return Err(DecoderError::Bug); |
| 230 | } |
| 231 | for (dst, src) in ch0.chunks_exact_mut(32).zip(self.out[0].iter_mut()) { |
| 232 | self.qmf[0].synth(src, dst); |
| 233 | } |
| 234 | if channels == 2 { |
| 235 | for (dst, src) in ch1.chunks_mut(32).zip(self.out[1].iter_mut()) { |
| 236 | self.qmf[1].synth(src, dst); |
| 237 | } |
| 238 | } |
| 239 | }, |
| 240 | _ => { |
| 241 | let ret = self.read_mp3_side_data(&mut br, &src[..frame_size], channels == 1); |
| 242 | match ret { |
| 243 | Err(DecoderError::MissingReference) => { |
| 244 | abuf.truncate_audio(0); |
| 245 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf); |
| 246 | frm.set_duration(Some(0)); |
| 247 | return Ok(frm.into_ref()); |
| 248 | }, |
| 249 | Err(err) => return Err(err), |
| 250 | Ok(()) => {}, |
| 251 | }; |
| 252 | let has_data = self.decode_layer3(channels as usize, mode_extension)?; |
| 253 | if !has_data { |
| 254 | let frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None); |
| 255 | return Ok(frm.into_ref()); |
| 256 | } |
| 257 | self.synth_layer3(mode, mode_extension); |
| 258 | for (dst, src) in ch0.chunks_exact_mut(32).zip(self.out[0].iter_mut()) { |
| 259 | self.qmf[0].synth(src, dst); |
| 260 | } |
| 261 | if channels == 2 { |
| 262 | for (dst, src) in ch1.chunks_mut(32).zip(self.out[1].iter_mut()) { |
| 263 | self.qmf[1].synth(src, dst); |
| 264 | } |
| 265 | } |
| 266 | }, |
| 267 | }; |
| 268 | |
| 269 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf); |
| 270 | frm.set_duration(Some(nsamples as u64)); |
| 271 | frm.set_keyframe(true); |
| 272 | Ok(frm.into_ref()) |
| 273 | } else { |
| 274 | Err(DecoderError::Bug) |
| 275 | } |
| 276 | } |
| 277 | fn flush(&mut self) { |
| 278 | for qmf in self.qmf.iter_mut() { |
| 279 | *qmf = QMF::new(); |
| 280 | } |
| 281 | self.bytebuf.clear(); |
| 282 | self.ctx.reset(); |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | impl NAOptionHandler for MPADecoder { |
| 287 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } |
| 288 | fn set_options(&mut self, _options: &[NAOption]) { } |
| 289 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } |
| 290 | } |
| 291 | |
| 292 | pub fn get_decoder_mp2() -> Box<dyn NADecoder + Send> { |
| 293 | Box::new(MPADecoder::new(1)) |
| 294 | } |
| 295 | |
| 296 | pub fn get_decoder_mp3() -> Box<dyn NADecoder + Send> { |
| 297 | Box::new(MPADecoder::new(2)) |
| 298 | } |
| 299 | |
| 300 | #[derive(Clone,Copy,Debug)] |
| 301 | struct MPAHeader { |
| 302 | layer: u8, |
| 303 | srate: u32, |
| 304 | channels: u8, |
| 305 | frame_size: usize, |
| 306 | nsamples: usize, |
| 307 | } |
| 308 | |
| 309 | impl PartialEq for MPAHeader { |
| 310 | fn eq(&self, other: &Self) -> bool { |
| 311 | self.layer == other.layer && |
| 312 | self.srate == other.srate && |
| 313 | self.channels == other.channels |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | #[derive(Default)] |
| 318 | struct MPAPacketiser { |
| 319 | buf: Vec<u8>, |
| 320 | hdr: Option<MPAHeader>, |
| 321 | } |
| 322 | |
| 323 | impl MPAPacketiser { |
| 324 | fn new() -> Self { Self::default() } |
| 325 | fn parse_header(&self, off: usize) -> DecoderResult<MPAHeader> { |
| 326 | if self.buf.len() < off + 4 { return Err(DecoderError::ShortData); } |
| 327 | |
| 328 | let mut br = BitReader::new(&self.buf[off..], BitReaderMode::BE); |
| 329 | |
| 330 | let syncword = br.read(11)?; |
| 331 | if syncword != 0x7FF { return Err(DecoderError::InvalidData); } |
| 332 | let id = br.read(2)?; |
| 333 | if id == 1 { return Err(DecoderError::InvalidData); } |
| 334 | let layer = (br.read(2)? ^ 3) as u8; |
| 335 | if layer == 3 { return Err(DecoderError::InvalidData); } |
| 336 | let _protection = br.read_bool()?; |
| 337 | let bitrate_index = br.read(4)? as usize; |
| 338 | if bitrate_index == 15 { return Err(DecoderError::InvalidData); } |
| 339 | if bitrate_index == 0 { |
| 340 | //todo freeform eventually |
| 341 | unimplemented!(); |
| 342 | } |
| 343 | let mut sf_idx = br.read(2)? as usize; |
| 344 | if sf_idx == 3 { return Err(DecoderError::InvalidData); } |
| 345 | let padding = br.read_bool()?; |
| 346 | let _private = br.read_bool()?; |
| 347 | let mode = br.read(2)? as u8; |
| 348 | |
| 349 | match id { |
| 350 | 0 => sf_idx += 6, |
| 351 | 2 => sf_idx += 3, |
| 352 | _ => {}, |
| 353 | }; |
| 354 | let mpeg1 = id == 3; |
| 355 | let srate = SAMPLING_RATE[sf_idx]; |
| 356 | let channels = if mode == 3 { 1 } else { 2 }; |
| 357 | let bitrate = BITRATE[if mpeg1 { 0 } else { 1 }][layer as usize][bitrate_index]; |
| 358 | let frame_size = match layer { |
| 359 | 0 => { |
| 360 | ((SAMPLES / 3 / 8 * 1000 * (bitrate as usize) / (srate as usize)) & !3) + if padding { 4 } else { 0 } |
| 361 | }, |
| 362 | 2 if !mpeg1 => { |
| 363 | SAMPLES / 2 / 8 * 1000 * (bitrate as usize) / (srate as usize) + if padding { 1 } else { 0 } |
| 364 | }, |
| 365 | _ => { |
| 366 | SAMPLES / 8 * 1000 * (bitrate as usize) / (srate as usize) + if padding { 1 } else { 0 } |
| 367 | }, |
| 368 | }; |
| 369 | let nsamples = if mpeg1 { SAMPLES } else { SAMPLES / 2 }; |
| 370 | |
| 371 | Ok(MPAHeader{ layer, srate, channels, frame_size, nsamples }) |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | impl NAPacketiser for MPAPacketiser { |
| 376 | fn add_data(&mut self, src: &[u8]) -> bool { |
| 377 | self.buf.extend_from_slice(src); |
| 378 | self.buf.len() < 4096 |
| 379 | } |
| 380 | fn parse_stream(&mut self, id: u32) -> DecoderResult<NAStreamRef> { |
| 381 | if self.hdr.is_none() { |
| 382 | if self.buf.len() < 4 { |
| 383 | return Err(DecoderError::ShortData); |
| 384 | } |
| 385 | let hdr = self.parse_header(0)?; |
| 386 | self.hdr = Some(hdr); |
| 387 | } |
| 388 | let hdr = self.hdr.unwrap(); |
| 389 | let mut duration = 0; |
| 390 | if hdr.layer == 2 { // check for Xing/LAME info |
| 391 | let mpeg1 = hdr.srate >= 32000; |
| 392 | let offset = match (mpeg1, hdr.channels) { |
| 393 | (true, 1) => 24, |
| 394 | (true, _) => 36, |
| 395 | (false, 1) => 13, |
| 396 | (false, _) => 21, |
| 397 | }; |
| 398 | if self.buf.len() >= offset + 12 && (&self.buf[offset..][..4] == b"Xing" || &self.buf[offset..][..4] == b"Info") { |
| 399 | let flags = read_u32be(&self.buf[offset + 4..]).unwrap_or(0); |
| 400 | if (flags & 1) != 0 { |
| 401 | duration = u64::from(read_u32be(&self.buf[offset + 8..]).unwrap_or(0)); |
| 402 | } |
| 403 | } else if self.buf.len() >= offset + 18 && &self.buf[offset..][..6] == b"VBRI\x00\x01" { |
| 404 | duration = u64::from(read_u32be(&self.buf[offset + 14..]).unwrap_or(0)); |
| 405 | } |
| 406 | } |
| 407 | let ainfo = NAAudioInfo::new(hdr.srate, hdr.channels, SND_F32P_FORMAT, hdr.nsamples); |
| 408 | let cname = match hdr.layer { |
| 409 | 0 => "mp1", |
| 410 | 1 => "mp2", |
| 411 | _ => "mp3", |
| 412 | }; |
| 413 | let info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ainfo), None); |
| 414 | Ok(NAStream::new(StreamType::Audio, id, info, hdr.nsamples as u32, hdr.srate, duration).into_ref()) |
| 415 | } |
| 416 | fn skip_junk(&mut self) -> DecoderResult<usize> { |
| 417 | if self.buf.len() <= 2 { |
| 418 | return Ok(0); |
| 419 | } |
| 420 | let mut off = 0; |
| 421 | let mut hdr = u16::from(self.buf[0]) * 256 + u16::from(self.buf[1]); |
| 422 | let mut iter = self.buf[2..].iter(); |
| 423 | loop { |
| 424 | if (hdr & 0xFFE0) != 0xFFE0 { |
| 425 | let ret = self.parse_header(off); |
| 426 | match ret { |
| 427 | Ok(hdr) => { |
| 428 | if self.hdr.is_none() { |
| 429 | self.hdr = Some(hdr); |
| 430 | } |
| 431 | if self.hdr.unwrap() != hdr { // header is valid but mismatches |
| 432 | self.buf.drain(..off + 1); |
| 433 | return Err(DecoderError::InvalidData); |
| 434 | } |
| 435 | break; |
| 436 | }, |
| 437 | Err(err) => { |
| 438 | self.buf.drain(..off + 1); |
| 439 | return Err(err); |
| 440 | }, |
| 441 | }; |
| 442 | } |
| 443 | off += 1; |
| 444 | if let Some(&b) = iter.next() { |
| 445 | hdr = (hdr << 8) | u16::from(b); |
| 446 | } else { |
| 447 | break; |
| 448 | } |
| 449 | } |
| 450 | self.buf.drain(..off); |
| 451 | Ok(off) |
| 452 | } |
| 453 | fn get_packet(&mut self, stream: NAStreamRef) -> DecoderResult<Option<NAPacket>> { |
| 454 | if self.buf.len() < 4 { |
| 455 | return Err(DecoderError::ShortData); |
| 456 | } |
| 457 | let hdr = self.parse_header(0)?; |
| 458 | if self.hdr.is_none() { |
| 459 | self.hdr = Some(hdr); |
| 460 | } |
| 461 | if self.hdr.unwrap() != hdr { |
| 462 | return Err(DecoderError::InvalidData); |
| 463 | } |
| 464 | if hdr.frame_size <= self.buf.len() { |
| 465 | let mut data = Vec::with_capacity(hdr.frame_size); |
| 466 | data.extend_from_slice(&self.buf[..hdr.frame_size]); |
| 467 | self.buf.drain(..hdr.frame_size); |
| 468 | let ts = NATimeInfo::new(None, None, Some(1), hdr.nsamples as u32, hdr.srate); |
| 469 | Ok(Some(NAPacket::new(stream, ts, true, data))) |
| 470 | } else { |
| 471 | Ok(None) |
| 472 | } |
| 473 | } |
| 474 | fn reset(&mut self) { |
| 475 | self.buf.clear(); |
| 476 | } |
| 477 | fn bytes_left(&self) -> usize { self.buf.len() } |
| 478 | } |
| 479 | |
| 480 | pub fn get_packetiser() -> Box<dyn NAPacketiser + Send> { |
| 481 | Box::new(MPAPacketiser::new()) |
| 482 | } |
| 483 | |
| 484 | #[cfg(test)] |
| 485 | mod test { |
| 486 | use nihav_core::codecs::RegisteredDecoders; |
| 487 | use nihav_core::demuxers::RegisteredDemuxers; |
| 488 | use nihav_codec_support::test::dec_video::test_decode_audio; |
| 489 | use crate::mpeg_register_all_decoders; |
| 490 | use nihav_flash::flash_register_all_demuxers; |
| 491 | use std::io::Read; |
| 492 | use nihav_core::codecs::NAPacketiser; |
| 493 | |
| 494 | #[test] |
| 495 | fn test_mpeg1_layer3_mono() { |
| 496 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 497 | flash_register_all_demuxers(&mut dmx_reg); |
| 498 | let mut dec_reg = RegisteredDecoders::new(); |
| 499 | mpeg_register_all_decoders(&mut dec_reg); |
| 500 | |
| 501 | // sample: https://samples.mplayerhq.hu/FLV/flash_video_5/i_004.flv |
| 502 | let file = "assets/Flash/i_004.flv"; |
| 503 | test_decode_audio("flv", file, Some(6000), None/*Some("mp3_1")*/, &dmx_reg, &dec_reg); |
| 504 | } |
| 505 | #[test] |
| 506 | fn test_mpeg1_layer3_stereo() { |
| 507 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 508 | flash_register_all_demuxers(&mut dmx_reg); |
| 509 | let mut dec_reg = RegisteredDecoders::new(); |
| 510 | mpeg_register_all_decoders(&mut dec_reg); |
| 511 | |
| 512 | // sample: https://samples.mplayerhq.hu/FLV/venture_030_ivcp_001_8bit.flv |
| 513 | let file = "assets/Flash/venture_030_ivcp_001_8bit.flv"; |
| 514 | test_decode_audio("flv", file, Some(7200), None/*Some("mp3_2")*/, &dmx_reg, &dec_reg); |
| 515 | } |
| 516 | #[test] |
| 517 | fn test_mpeg2_layer3() { |
| 518 | let mut dmx_reg = RegisteredDemuxers::new(); |
| 519 | flash_register_all_demuxers(&mut dmx_reg); |
| 520 | let mut dec_reg = RegisteredDecoders::new(); |
| 521 | mpeg_register_all_decoders(&mut dec_reg); |
| 522 | |
| 523 | // sample: https://samples.mplayerhq.hu/FLV/flash_with_alpha/lection2-2.flv |
| 524 | let file = "assets/Flash/lection2-2.flv"; |
| 525 | test_decode_audio("flv", file, Some(6000), None/*Some("mp3_3")*/, &dmx_reg, &dec_reg); |
| 526 | } |
| 527 | #[test] |
| 528 | fn test_mpa_packetiser() { |
| 529 | let mut buf = [0; 16384]; |
| 530 | // sample from a private collection |
| 531 | let mut file = std::fs::File::open("assets/MPEG/1.mp3").unwrap(); |
| 532 | |
| 533 | let mut pkts = super::MPAPacketiser::new(); |
| 534 | file.read_exact(&mut buf).unwrap(); |
| 535 | pkts.add_data(&buf); |
| 536 | let stream = pkts.parse_stream(0).unwrap(); |
| 537 | let mut frame_sizes = Vec::with_capacity(15); |
| 538 | while let Some(pkt) = pkts.get_packet(stream.clone()).unwrap() { |
| 539 | let frame_size = pkt.get_buffer().len(); |
| 540 | println!("pkt size {}", frame_size); |
| 541 | frame_sizes.push(frame_size); |
| 542 | } |
| 543 | assert_eq!(&frame_sizes, &[1044, 1044, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1044, 1045, 1045, 1045]); |
| 544 | } |
| 545 | } |
| 546 | |
| 547 | const BITRATE: [[[u32; 15]; 3]; 2] = [ |
| 548 | [ |
| 549 | [ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 ], |
| 550 | [ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 ], |
| 551 | [ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 ] |
| 552 | ], [ |
| 553 | [ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 ], |
| 554 | [ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 ], |
| 555 | [ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 ] |
| 556 | ] |
| 557 | ]; |
| 558 | |
| 559 | const SAMPLING_RATE: [u32; 9] = [ 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 ]; |