]>
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<()> { | |
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!(), | |
9f9a08fb KS |
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 | }, | |
16cca4d3 KS |
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 | ||
9f9a08fb KS |
292 | pub fn get_decoder_mp2() -> Box<dyn NADecoder + Send> { |
293 | Box::new(MPADecoder::new(1)) | |
294 | } | |
295 | ||
16cca4d3 KS |
296 | pub fn get_decoder_mp3() -> Box<dyn NADecoder + Send> { |
297 | Box::new(MPADecoder::new(2)) | |
298 | } | |
299 | ||
f27c73df KS |
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)?; | |
7f7356a0 | 331 | if syncword != 0x7FF { return Err(DecoderError::InvalidData); } |
f27c73df | 332 | let id = br.read(2)?; |
7f7356a0 | 333 | if id == 1 { return Err(DecoderError::InvalidData); } |
f27c73df | 334 | let layer = (br.read(2)? ^ 3) as u8; |
7f7356a0 | 335 | if layer == 3 { return Err(DecoderError::InvalidData); } |
f27c73df KS |
336 | let _protection = br.read_bool()?; |
337 | let bitrate_index = br.read(4)? as usize; | |
7f7356a0 | 338 | if bitrate_index == 15 { return Err(DecoderError::InvalidData); } |
f27c73df KS |
339 | if bitrate_index == 0 { |
340 | //todo freeform eventually | |
341 | unimplemented!(); | |
342 | } | |
343 | let mut sf_idx = br.read(2)? as usize; | |
7f7356a0 | 344 | if sf_idx == 3 { return Err(DecoderError::InvalidData); } |
f27c73df KS |
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 { | |
1b56382e | 376 | fn attach_stream(&mut self, _stream: NAStreamRef) {} |
f27c73df KS |
377 | fn add_data(&mut self, src: &[u8]) -> bool { |
378 | self.buf.extend_from_slice(src); | |
379 | self.buf.len() < 4096 | |
380 | } | |
381 | fn parse_stream(&mut self, id: u32) -> DecoderResult<NAStreamRef> { | |
382 | if self.hdr.is_none() { | |
383 | if self.buf.len() < 4 { | |
384 | return Err(DecoderError::ShortData); | |
385 | } | |
386 | let hdr = self.parse_header(0)?; | |
387 | self.hdr = Some(hdr); | |
388 | } | |
389 | let hdr = self.hdr.unwrap(); | |
a091b968 KS |
390 | let mut duration = 0; |
391 | if hdr.layer == 2 { // check for Xing/LAME info | |
392 | let mpeg1 = hdr.srate >= 32000; | |
393 | let offset = match (mpeg1, hdr.channels) { | |
394 | (true, 1) => 24, | |
395 | (true, _) => 36, | |
396 | (false, 1) => 13, | |
397 | (false, _) => 21, | |
398 | }; | |
399 | if self.buf.len() >= offset + 12 && (&self.buf[offset..][..4] == b"Xing" || &self.buf[offset..][..4] == b"Info") { | |
400 | let flags = read_u32be(&self.buf[offset + 4..]).unwrap_or(0); | |
401 | if (flags & 1) != 0 { | |
402 | duration = u64::from(read_u32be(&self.buf[offset + 8..]).unwrap_or(0)); | |
403 | } | |
418df65e KS |
404 | } else if self.buf.len() >= offset + 18 && &self.buf[offset..][..6] == b"VBRI\x00\x01" { |
405 | duration = u64::from(read_u32be(&self.buf[offset + 14..]).unwrap_or(0)); | |
a091b968 KS |
406 | } |
407 | } | |
f27c73df | 408 | let ainfo = NAAudioInfo::new(hdr.srate, hdr.channels, SND_F32P_FORMAT, hdr.nsamples); |
9f9a08fb KS |
409 | let cname = match hdr.layer { |
410 | 0 => "mp1", | |
411 | 1 => "mp2", | |
412 | _ => "mp3", | |
413 | }; | |
414 | let info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ainfo), None); | |
a091b968 | 415 | Ok(NAStream::new(StreamType::Audio, id, info, hdr.nsamples as u32, hdr.srate, duration).into_ref()) |
f27c73df KS |
416 | } |
417 | fn skip_junk(&mut self) -> DecoderResult<usize> { | |
418 | if self.buf.len() <= 2 { | |
419 | return Ok(0); | |
420 | } | |
421 | let mut off = 0; | |
422 | let mut hdr = u16::from(self.buf[0]) * 256 + u16::from(self.buf[1]); | |
423 | let mut iter = self.buf[2..].iter(); | |
424 | loop { | |
425 | if (hdr & 0xFFE0) != 0xFFE0 { | |
426 | let ret = self.parse_header(off); | |
427 | match ret { | |
428 | Ok(hdr) => { | |
429 | if self.hdr.is_none() { | |
430 | self.hdr = Some(hdr); | |
431 | } | |
432 | if self.hdr.unwrap() != hdr { // header is valid but mismatches | |
433 | self.buf.drain(..off + 1); | |
434 | return Err(DecoderError::InvalidData); | |
435 | } | |
436 | break; | |
437 | }, | |
438 | Err(err) => { | |
439 | self.buf.drain(..off + 1); | |
440 | return Err(err); | |
441 | }, | |
442 | }; | |
443 | } | |
444 | off += 1; | |
445 | if let Some(&b) = iter.next() { | |
446 | hdr = (hdr << 8) | u16::from(b); | |
447 | } else { | |
448 | break; | |
449 | } | |
450 | } | |
451 | self.buf.drain(..off); | |
452 | Ok(off) | |
453 | } | |
454 | fn get_packet(&mut self, stream: NAStreamRef) -> DecoderResult<Option<NAPacket>> { | |
455 | if self.buf.len() < 4 { | |
456 | return Err(DecoderError::ShortData); | |
457 | } | |
458 | let hdr = self.parse_header(0)?; | |
459 | if self.hdr.is_none() { | |
460 | self.hdr = Some(hdr); | |
461 | } | |
462 | if self.hdr.unwrap() != hdr { | |
463 | return Err(DecoderError::InvalidData); | |
464 | } | |
465 | if hdr.frame_size <= self.buf.len() { | |
466 | let mut data = Vec::with_capacity(hdr.frame_size); | |
467 | data.extend_from_slice(&self.buf[..hdr.frame_size]); | |
468 | self.buf.drain(..hdr.frame_size); | |
469 | let ts = NATimeInfo::new(None, None, Some(1), hdr.nsamples as u32, hdr.srate); | |
470 | Ok(Some(NAPacket::new(stream, ts, true, data))) | |
471 | } else { | |
472 | Ok(None) | |
473 | } | |
474 | } | |
475 | fn reset(&mut self) { | |
476 | self.buf.clear(); | |
477 | } | |
7f754c49 | 478 | fn bytes_left(&self) -> usize { self.buf.len() } |
f27c73df KS |
479 | } |
480 | ||
481 | pub fn get_packetiser() -> Box<dyn NAPacketiser + Send> { | |
482 | Box::new(MPAPacketiser::new()) | |
483 | } | |
484 | ||
16cca4d3 KS |
485 | #[cfg(test)] |
486 | mod test { | |
487 | use nihav_core::codecs::RegisteredDecoders; | |
488 | use nihav_core::demuxers::RegisteredDemuxers; | |
489 | use nihav_codec_support::test::dec_video::test_decode_audio; | |
490 | use crate::mpeg_register_all_decoders; | |
491 | use nihav_flash::flash_register_all_demuxers; | |
f27c73df KS |
492 | use std::io::Read; |
493 | use nihav_core::codecs::NAPacketiser; | |
494 | ||
16cca4d3 KS |
495 | #[test] |
496 | fn test_mpeg1_layer3_mono() { | |
497 | let mut dmx_reg = RegisteredDemuxers::new(); | |
498 | flash_register_all_demuxers(&mut dmx_reg); | |
499 | let mut dec_reg = RegisteredDecoders::new(); | |
500 | mpeg_register_all_decoders(&mut dec_reg); | |
501 | ||
886cde48 | 502 | // sample: https://samples.mplayerhq.hu/FLV/flash_video_5/i_004.flv |
16cca4d3 KS |
503 | let file = "assets/Flash/i_004.flv"; |
504 | test_decode_audio("flv", file, Some(6000), None/*Some("mp3_1")*/, &dmx_reg, &dec_reg); | |
505 | } | |
506 | #[test] | |
507 | fn test_mpeg1_layer3_stereo() { | |
508 | let mut dmx_reg = RegisteredDemuxers::new(); | |
509 | flash_register_all_demuxers(&mut dmx_reg); | |
510 | let mut dec_reg = RegisteredDecoders::new(); | |
511 | mpeg_register_all_decoders(&mut dec_reg); | |
512 | ||
886cde48 | 513 | // sample: https://samples.mplayerhq.hu/FLV/venture_030_ivcp_001_8bit.flv |
16cca4d3 KS |
514 | let file = "assets/Flash/venture_030_ivcp_001_8bit.flv"; |
515 | test_decode_audio("flv", file, Some(7200), None/*Some("mp3_2")*/, &dmx_reg, &dec_reg); | |
516 | } | |
517 | #[test] | |
518 | fn test_mpeg2_layer3() { | |
519 | let mut dmx_reg = RegisteredDemuxers::new(); | |
520 | flash_register_all_demuxers(&mut dmx_reg); | |
521 | let mut dec_reg = RegisteredDecoders::new(); | |
522 | mpeg_register_all_decoders(&mut dec_reg); | |
523 | ||
886cde48 | 524 | // sample: https://samples.mplayerhq.hu/FLV/flash_with_alpha/lection2-2.flv |
16cca4d3 KS |
525 | let file = "assets/Flash/lection2-2.flv"; |
526 | test_decode_audio("flv", file, Some(6000), None/*Some("mp3_3")*/, &dmx_reg, &dec_reg); | |
527 | } | |
f27c73df KS |
528 | #[test] |
529 | fn test_mpa_packetiser() { | |
530 | let mut buf = [0; 16384]; | |
886cde48 | 531 | // sample from a private collection |
f27c73df KS |
532 | let mut file = std::fs::File::open("assets/MPEG/1.mp3").unwrap(); |
533 | ||
534 | let mut pkts = super::MPAPacketiser::new(); | |
535 | file.read_exact(&mut buf).unwrap(); | |
536 | pkts.add_data(&buf); | |
537 | let stream = pkts.parse_stream(0).unwrap(); | |
538 | let mut frame_sizes = Vec::with_capacity(15); | |
539 | while let Some(pkt) = pkts.get_packet(stream.clone()).unwrap() { | |
540 | let frame_size = pkt.get_buffer().len(); | |
541 | println!("pkt size {}", frame_size); | |
542 | frame_sizes.push(frame_size); | |
543 | } | |
544 | assert_eq!(&frame_sizes, &[1044, 1044, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1044, 1045, 1045, 1045]); | |
545 | } | |
16cca4d3 KS |
546 | } |
547 | ||
548 | const BITRATE: [[[u32; 15]; 3]; 2] = [ | |
549 | [ | |
550 | [ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 ], | |
551 | [ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 ], | |
552 | [ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 ] | |
553 | ], [ | |
554 | [ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 ], | |
555 | [ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 ], | |
556 | [ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 ] | |
557 | ] | |
558 | ]; | |
559 | ||
560 | const SAMPLING_RATE: [u32; 9] = [ 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 ]; |