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