rmmux: better audio codec flavour detection
[nihav.git] / nihav-realmedia / src / muxers / rmvb / audiostream.rs
CommitLineData
9dc1fb4b
KS
1use nihav_core::frame::*;
2use nihav_core::muxers::*;
3use super::RMStreamWriter;
4
5// fourcc, codec name, interleaver, version
6static AUDIO_CODEC_REGISTRY: &[(&[u8;4], &str, &[u8;4], u8)] = &[
7 (b"lpcJ", "ra14.4", b"Int0", 3),
8 (b"28_8", "ra28.8", b"Int4", 4),
9 (b"cook", "cook", b"genr", 5),
10 (b"dnet", "ac3", b"Int0", 4),
11 (b"sipr", "sipro", b"sipr", 4),
12 (b"atrc", "atrac3", b"genr", 5),
13 (b"LSD:", "ralf", b"Int0", 6),
14 (b"raac", "aac", b"vbrs", 5),
15 (b"racp", "aac", b"vbrf", 5),
16];
17
18struct InterleaveParams {
f62e2ae0
KS
19 sample_rate: u32,
20 channels: u8,
9dc1fb4b
KS
21 block_size: usize,
22 factor: usize,
23 frames_per_blk: usize,
24}
25
26trait Interleaver {
27 fn get_flavor(&self) -> usize;
28 fn get_block_size(&self) -> usize;
29 fn get_factor(&self) -> usize;
30 fn get_frames_per_block(&self) -> usize;
c5963b17 31 fn is_empty(&self) -> bool;
9dc1fb4b
KS
32 fn add_packet(&mut self, src: &[u8]) -> bool;
33 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)>;
34 fn flush(&mut self);
35
36 fn get_frame_size(&self) -> usize { self.get_block_size() / self.get_frames_per_block() }
37}
38
39struct NoInterleaver {
40 frame_size: usize,
41 pkt: Option<Vec<u8>>,
42}
43impl Interleaver for NoInterleaver {
44 fn get_flavor(&self) -> usize { 0 }
45 fn get_block_size(&self) -> usize { self.frame_size }
46 fn get_factor(&self) -> usize { 1 }
47 fn get_frames_per_block(&self) -> usize { 1 }
c5963b17 48 fn is_empty(&self) -> bool { self.pkt.is_none() }
9dc1fb4b
KS
49 fn add_packet(&mut self, src: &[u8]) -> bool {
50 if self.pkt.is_none() {
51 self.pkt = Some(src.to_vec());
52 true
53 } else {
54 false
55 }
56 }
57 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
58 let mut ret = None;
59 std::mem::swap(&mut self.pkt, &mut ret);
60 if let Some(pkt) = ret {
61 Some((pkt, true))
62 } else {
63 None
64 }
65 }
66 fn flush(&mut self) {}
67}
68
69struct Int4Interleaver {
70 flavor: usize,
71 factor: usize,
72 frame_size: usize,
73 block_size: usize,
74 fpb: usize,
75 cur_frame: usize,
76 rd_block: usize,
77 buf: Vec<u8>,
78 map: Vec<usize>,
79}
80impl Int4Interleaver {
81 fn new(frame_size: usize) -> MuxerResult<Self> {
82 let params = RA_28_8_INTERLEAVE_PARAMS;
83 for (flavor, entry) in params.iter().enumerate() {
84 if entry.block_size / entry.frames_per_blk == frame_size {
85 let full_size = entry.frames_per_blk * entry.factor;
86 let mut map = vec![0; full_size];
87 for i in 0..full_size {
88 let fval = i * entry.factor;
89 let mapped = (fval % full_size) + fval / full_size;
90 map[mapped] = i;
91 }
92
93 return Ok(Self {
94 flavor,
95 frame_size,
96 map,
97 factor: entry.factor,
98 block_size: entry.block_size,
99 fpb: entry.frames_per_blk,
100 cur_frame: 0,
101 rd_block: 0,
102 buf: vec![0; entry.block_size * entry.factor],
103 });
104 }
105 }
106 Err(MuxerError::UnsupportedFormat)
107 }
108}
109impl Interleaver for Int4Interleaver {
110 fn get_flavor(&self) -> usize { self.flavor }
111 fn get_block_size(&self) -> usize { self.block_size }
112 fn get_factor(&self) -> usize { self.factor }
113 fn get_frames_per_block(&self) -> usize { self.fpb }
c5963b17 114 fn is_empty(&self) -> bool { self.cur_frame == 0 }
9dc1fb4b
KS
115 fn add_packet(&mut self, src: &[u8]) -> bool {
116 if self.cur_frame == self.factor * self.fpb {
117 return false;
118 }
119 let pos = self.map[self.cur_frame];
120 self.buf[pos * self.frame_size..][..self.frame_size].copy_from_slice(&src);
121 self.cur_frame += 1;
122 true
123 }
124 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
125 if self.cur_frame == self.factor * self.fpb {
126 let first = self.rd_block == 0;
127 let src = &self.buf[self.rd_block * self.block_size..][..self.block_size];
128 self.rd_block += 1;
129 if self.rd_block == self.factor {
130 self.rd_block = 0;
131 self.cur_frame = 0;
132 }
133 Some((src.to_vec(), first))
134 } else {
135 None
136 }
137 }
138 fn flush(&mut self) {
139 if self.cur_frame != 0 {
140 self.cur_frame = self.factor * self.fpb;
141 }
142 }
143}
144
145struct GenericInterleaver {
146 flavor: usize,
147 factor: usize,
148 frame_size: usize,
149 block_size: usize,
150 fpb: usize,
151 cur_frame: usize,
152 rd_block: usize,
153 buf: Vec<u8>,
154 map: Vec<usize>,
155}
156impl GenericInterleaver {
f62e2ae0 157 fn new(ainfo: NAAudioInfo, frame_size: usize, fcc: [u8; 4]) -> MuxerResult<Self> {
9dc1fb4b
KS
158 let params = match &fcc {
159 b"atrc" => ATRAC_INTERLEAVE_PARAMS,
160 b"cook" => COOK_INTERLEAVE_PARAMS,
161 b"sipr" => SIPRO_INTERLEAVE_PARAMS,
162 _ => return Err(MuxerError::UnsupportedFormat),
163 };
164 for (flavor, entry) in params.iter().enumerate() {
f62e2ae0
KS
165 if entry.sample_rate != 0 && entry.sample_rate != ainfo.sample_rate {
166 continue;
167 }
168 if entry.channels != 0 && entry.channels != ainfo.channels {
169 continue;
170 }
9dc1fb4b
KS
171 if entry.block_size / entry.frames_per_blk == frame_size {
172 let full_size = entry.frames_per_blk * entry.factor;
173 let mut map = vec![0; full_size];
174
175 let mut frm = 0;
176 let mut blk = 0;
177 let mut even = true;
178 for dst in map.iter_mut() {
179 let mapped = blk * entry.frames_per_blk + frm;
180 blk += 2;
181 if blk >= entry.factor {
182 if even {
183 blk = 1;
184 } else {
185 blk = 0;
186 frm += 1;
187 }
188 even = !even;
189 }
190 *dst = mapped;
191 }
192
193 return Ok(Self {
194 flavor,
195 frame_size,
196 map,
197 factor: entry.factor,
198 block_size: entry.block_size,
199 fpb: entry.frames_per_blk,
200 cur_frame: 0,
201 rd_block: 0,
202 buf: vec![0; entry.block_size * entry.factor],
203 });
204 }
205 }
206 Err(MuxerError::UnsupportedFormat)
207 }
208}
209impl Interleaver for GenericInterleaver {
210 fn get_flavor(&self) -> usize { self.flavor }
211 fn get_block_size(&self) -> usize { self.block_size }
212 fn get_factor(&self) -> usize { self.factor }
213 fn get_frames_per_block(&self) -> usize { self.fpb }
c5963b17 214 fn is_empty(&self) -> bool { self.cur_frame == 0 }
9dc1fb4b
KS
215 fn add_packet(&mut self, src: &[u8]) -> bool {
216 if self.cur_frame == self.factor * self.fpb {
217 return false;
218 }
219 let pos = self.map[self.cur_frame];
220 self.buf[pos * self.frame_size..][..self.frame_size].copy_from_slice(&src);
221 self.cur_frame += 1;
222 true
223 }
224 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
225 if self.cur_frame == self.factor * self.fpb {
226 let first = self.rd_block == 0;
227 let src = &self.buf[self.rd_block * self.block_size..][..self.block_size];
228 self.rd_block += 1;
229 if self.rd_block == self.factor {
230 self.rd_block = 0;
231 self.cur_frame = 0;
232 }
233 Some((src.to_vec(), first))
234 } else {
235 None
236 }
237 }
238 fn flush(&mut self) {
239 if self.cur_frame != 0 {
240 self.cur_frame = self.factor * self.fpb;
241 }
242 }
243}
244
245struct SiproInterleaver {
246 block_size: usize,
247 factor: usize,
248 flavor: usize,
249 buf: Vec<u8>,
250 wr_pos: usize,
251 rd_pos: usize,
252}
253impl SiproInterleaver {
254 fn new(mut frame_size: usize) -> MuxerResult<Self> {
255 if frame_size == 0 {
256 return Err(MuxerError::UnsupportedFormat);
257 }
258 while frame_size < 200 {
259 frame_size <<= 1;
260 }
261 for (flavor, entry) in SIPRO_INTERLEAVE_PARAMS.iter().enumerate() {
262 if entry.block_size == frame_size {
263 return Ok(Self {
264 block_size: entry.block_size,
265 factor: entry.factor,
266 flavor,
267 buf: vec![0; entry.block_size * entry.factor],
268 wr_pos: 0,
269 rd_pos: 0,
270 });
271 }
272 }
273 Err(MuxerError::UnsupportedFormat)
274 }
275}
276impl Interleaver for SiproInterleaver {
277 fn get_flavor(&self) -> usize { self.flavor }
278 fn get_block_size(&self) -> usize { self.block_size }
279 fn get_factor(&self) -> usize { self.factor }
280 fn get_frames_per_block(&self) -> usize { 1 }
c5963b17 281 fn is_empty(&self) -> bool { self.wr_pos == 0 }
9dc1fb4b
KS
282 fn add_packet(&mut self, src: &[u8]) -> bool {
283 if self.wr_pos < self.factor {
284 self.buf[self.wr_pos * self.block_size..][..self.block_size].copy_from_slice(src);
285 self.wr_pos += 1;
286 true
287 } else {
288 false
289 }
290 }
291 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
292 if self.wr_pos == self.factor {
293 let first = self.rd_pos == 0;
294 if self.rd_pos == 0 {
295 sipro_scramble(&mut self.buf, self.factor, self.block_size);
296 }
297 let ret = self.buf[self.rd_pos * self.block_size..][..self.block_size].to_vec();
298 self.rd_pos += 1;
299 if self.rd_pos == self.factor {
300 self.rd_pos = 0;
301 self.wr_pos = 0;
302 }
303 Some((ret, first))
304 } else {
305 None
306 }
307 }
308 fn flush(&mut self) {
309 if self.wr_pos != self.factor {
310 self.wr_pos = self.factor;
311 }
312 }
313}
314
315fn sipro_scramble(buf: &mut [u8], factor: usize, fsize: usize) {
316 let stride = factor * fsize * 2 / 96;
317 for &swap_pair in SIPRO_SWAPS.iter() {
318 let mut sidx = usize::from(swap_pair[0]) * stride;
319 let mut didx = usize::from(swap_pair[1]) * stride;
320 for _ in 0..stride {
321 let in0 = buf[sidx >> 1];
322 let in1 = buf[didx >> 1];
323 let nib0 = (in0 >> ((sidx & 1) * 4)) & 0xF;
324 let nib1 = (in1 >> ((didx & 1) * 4)) & 0xF;
325
326 buf[didx >> 1] = (nib0 << (4 * (didx & 1))) | (in1 & (0xF << (4 * (!didx & 1))));
327 buf[sidx >> 1] = (nib1 << (4 * (sidx & 1))) | (in0 & (0xF << (4 * (!sidx & 1))));
328
329 sidx += 1;
330 didx += 1;
331 }
332 }
333}
334
335struct AACInterleaver {
336 frame_size: usize,
337 data: Vec<u8>,
338 sizes: Vec<usize>,
339 full: bool,
340}
341impl AACInterleaver {
342 fn new(frame_size: usize) -> Self {
343 Self {
344 frame_size,
345 data: Vec::with_capacity(frame_size * 3 / 2),
346 sizes: Vec::with_capacity((frame_size / 128).max(8)),
347 full: false,
348 }
349 }
350}
351impl Interleaver for AACInterleaver {
352 fn get_flavor(&self) -> usize { 0 }
353 fn get_block_size(&self) -> usize { self.frame_size }
354 fn get_factor(&self) -> usize { 1 }
355 fn get_frames_per_block(&self) -> usize { 1 }
c5963b17 356 fn is_empty(&self) -> bool { self.data.is_empty() }
9dc1fb4b
KS
357 fn add_packet(&mut self, src: &[u8]) -> bool {
358 if !self.full {
359 self.data.extend_from_slice(src);
360 self.sizes.push(src.len());
361 if self.data.len() >= self.frame_size {
362 self.full = true;
363 }
364 true
365 } else {
366 false
367 }
368 }
369 fn get_packet(&mut self) -> Option<(Vec<u8>, bool)> {
370 if self.full {
371 let mut dst = Vec::with_capacity(self.frame_size);
372 let mut gw = GrowableMemoryWriter::new_write(&mut dst);
373 let mut bw = ByteWriter::new(&mut gw);
374 bw.write_u16be((self.sizes.len() * 16) as u16).unwrap();
375 for &pkt_size in self.sizes.iter() {
376 bw.write_u16be(pkt_size as u16).unwrap();
377 }
378 bw.write_buf(&self.data).unwrap();
379
380 self.data.clear();
381 self.sizes.clear();
382 self.full = false;
383
384 Some((dst, true))
385 } else {
386 None
387 }
388 }
389 fn flush(&mut self) {
390 if !self.sizes.is_empty() {
391 self.full = true;
392 }
393 }
394}
395
396struct InterleaveInfo {
397 fcc: [u8; 4],
398 il_fcc: [u8; 4],
399 block_size: usize,
400 frame_size: usize,
401 factor: usize,
402 flavor: usize,
403}
404
405struct AudioStreamWriter {
406 fcc: [u8; 4],
407 il_fcc: [u8; 4],
408 is_raw: bool,
409 version: u8,
410 header_pos: u64,
411 interleave: Box<dyn Interleaver>,
412 data_size: usize,
c5963b17
KS
413 first_time: u32,
414 last_time: u32,
415 size_in: usize,
416 size_out: usize,
9dc1fb4b
KS
417}
418
419impl RMStreamWriter for AudioStreamWriter {
420 fn write_header(&mut self, bw: &mut ByteWriter, astream: &NAStream) -> MuxerResult<()> {
421 self.header_pos = bw.tell();
422 if self.version < 6 {
423 bw.write_buf(b".ra\xFD")?;
424 bw.write_u16be(self.version.into())?;
425 }
426
427 let il_info = InterleaveInfo {
428 fcc: self.fcc,
429 il_fcc: self.il_fcc,
430 block_size: self.interleave.get_block_size(),
431 frame_size: self.interleave.get_frame_size(),
432 factor: self.interleave.get_factor(),
433 flavor: self.interleave.get_flavor(),
434 };
435
436 match self.version {
437 3 => write_aformat3(bw, astream, &il_info)?,
438 4 => write_aformat4(bw, astream, &il_info)?,
439 5 => write_aformat5(bw, astream, &il_info)?,
440 6 => write_lsd(bw, astream)?,
441 _ => unreachable!(),
442 }
443 Ok(())
444 }
c5963b17 445 fn queue_packet(&mut self, pkt: NAPacket, ms: u32) -> bool {
9dc1fb4b
KS
446 let src = pkt.get_buffer();
447 self.data_size += src.len();
448 let frame_size = self.interleave.get_frame_size();
c5963b17
KS
449 self.last_time = ms;
450 if self.interleave.is_empty() {
451 self.first_time = ms;
452 self.size_in = 0;
453 self.size_out = 0;
454 } else {
455 self.size_in += src.len() / frame_size;
456 }
9dc1fb4b
KS
457 if !self.is_raw {
458 let mut ret = false;
459 for frame in src.chunks(frame_size) {
460 ret = self.interleave.add_packet(frame);
461 }
462 ret
463 } else {
464 self.interleave.add_packet(&src)
465 }
466 }
c5963b17
KS
467 fn get_packet(&mut self) -> Option<(Vec<u8>, u32, bool)> {
468 if let Some((pkt, first)) = self.interleave.get_packet() {
469 let time_add = if self.last_time > self.first_time && self.size_in > 0 {
470 let size = pkt.len();
471 let time_add = (self.size_out * ((self.last_time - self.first_time) as usize) / self.size_in) as u32;
472 self.size_out += size / self.interleave.get_frame_size();
473 time_add
474 } else {
475 0
476 };
477 Some((pkt, self.first_time + time_add, first))
478 } else {
479 None
480 }
481 }
9dc1fb4b
KS
482 fn flush(&mut self) { self.interleave.flush() }
483 fn finish(&mut self, bw: &mut ByteWriter) -> MuxerResult<()> {
484 let cur_pos = bw.tell();
485 match self.version {
486 3 => {
487 bw.seek(SeekFrom::Start(self.header_pos + 18))?;
488 bw.write_u32be(self.data_size as u32)?;
489 },
490 4 | 5 => {
491 bw.seek(SeekFrom::Start(self.header_pos + 12))?;
492 bw.write_u32be(self.data_size/*+header_size*/ as u32)?;
493 bw.seek(SeekFrom::Current(12))?;
494 bw.write_u32be(self.data_size as u32)?;
495 },
496 6 => unimplemented!(),
497 _ => unreachable!(),
498 };
499 bw.seek(SeekFrom::Start(cur_pos))?;
500 Ok(())
501 }
502}
503
504fn write_audio_metadata(bw: &mut ByteWriter) -> MuxerResult<()> {
505 bw.write_byte(0)?; // title_string_length
506 bw.write_byte(0)?; // author_string_length
507 bw.write_byte(0)?; // copyright_string_length
508 bw.write_byte(0)?; // user_string_length
509 Ok(())
510}
511
512fn write_aformat3(bw: &mut ByteWriter, _stream: &NAStream, il_info: &InterleaveInfo) -> MuxerResult<()> {
513 let start = bw.tell();
514 bw.write_u16be(0)?; // header_bytes
515 bw.write_u16be(il_info.flavor as u16)?;
516 bw.write_u32be(il_info.frame_size as u32)?; // granularity
517 bw.write_u32be(0)?; // bytes per minute
518 bw.write_u32be(0)?; // total bytes
519 write_audio_metadata(bw)?;
520 bw.write_byte(0)?; //can_copy
521 bw.write_byte(4)?; // FCC length
522 bw.write_buf(&il_info.fcc)?;
523 let end = bw.tell();
524 bw.seek(SeekFrom::Start(start))?;
525 bw.write_u16be((end - start - 2) as u16)?;
526 bw.seek(SeekFrom::Start(end))?;
527
528 Ok(())
529}
530
531fn write_aformat4(bw: &mut ByteWriter, stream: &NAStream, il_info: &InterleaveInfo) -> MuxerResult<()> {
532 let info = stream.get_info().get_properties().get_audio_info().unwrap();
533
534 bw.write_u16be(0)?;
535 let start = bw.tell();
536 bw.write_buf(b".ra4")?;
537 bw.write_u32be(0)?; // data size
538 bw.write_u16be(4)?; // version
539 bw.write_u16be(0)?; // revision
540 bw.write_u16be(0)?; // header_bytes
541 bw.write_u16be(il_info.flavor as u16)?;
542 bw.write_u32be(il_info.frame_size as u32)?; // granularity
543 bw.write_u32be(0)?; // total bytes
544 bw.write_u32be(0)?; // bytes_per_minute
545 bw.write_u32be(0)?; // bytes_per_minute2
546 bw.write_u16be(il_info.factor as u16)?;
547 bw.write_u16be(il_info.block_size as u16)?;
548 bw.write_u16be(0)?; // user data
549 bw.write_u32be(info.sample_rate)?; // sample rate
550 bw.write_u32be(info.format.bits.into())?; // sample size
551 bw.write_u16be(info.channels.into())?; // num channels
552 bw.write_byte(4)?; // ileave ID len
553 bw.write_buf(&il_info.il_fcc)?;
554 bw.write_byte(4)?; // codec ID len
555 bw.write_buf(&il_info.fcc)?;
556 bw.write_byte(if &il_info.il_fcc == b"Int0" { 0 } else { 1 })?;
557 bw.write_byte(7)?; // can_copy
558 bw.write_byte(0)?; // stream_type
559 write_audio_metadata(bw)?;
560 let end = bw.tell();
561 bw.seek(SeekFrom::Start(start + 12))?;
562 bw.write_u16be((end - start - 4) as u16)?;
563 bw.seek(SeekFrom::Start(end))?;
564
565 Ok(())
566}
567
568fn write_aformat5(bw: &mut ByteWriter, stream: &NAStream, il_info: &InterleaveInfo) -> MuxerResult<()> {
569 let info = stream.get_info().get_properties().get_audio_info().unwrap();
570
571 bw.write_u16be(0)?;
572 let start = bw.tell();
573 bw.write_buf(b".ra5")?;
574 bw.write_u32be(0)?; // data size
575 bw.write_u16be(5)?; // version
576 bw.write_u16be(0)?; // revision
577 bw.write_u16be(0)?; // header_bytes
578 bw.write_u16be(il_info.flavor as u16)?;
579 bw.write_u32be(il_info.block_size as u32)?; // granularity
580 bw.write_u32be(0)?; // total bytes
581 bw.write_u32be(0)?; // bytes_per_minute
582 bw.write_u32be(0)?; // bytes_per_minute2
583 bw.write_u16be(il_info.factor as u16)?;
584 bw.write_u16be(il_info.block_size as u16)?;
585 bw.write_u16be(il_info.frame_size as u16)?;
586 bw.write_u16be(0)?; // user data
587 bw.write_u32be(info.sample_rate)?; // sample rate
588 bw.write_u32be(info.sample_rate)?; // actual sample rate
589 bw.write_u32be(info.format.bits.into())?; // sample size
590 bw.write_u16be(info.channels.into())?; // num channels
591 bw.write_buf(&il_info.il_fcc)?;
592 bw.write_buf(&il_info.fcc)?;
593 bw.write_byte(if &il_info.il_fcc == b"Int0" { 0 } else { 1 })?;
594 bw.write_byte(7)?; // can_copy
595 bw.write_byte(0)?; // stream_type
596 bw.write_byte(0)?; // has_interleave_pattern
597 if let Some(edata) = stream.get_info().get_extradata() {
598 if !matches!(&il_info.fcc, b"raac" | b"racp") {
599 bw.write_u32be(edata.len() as u32)?;
600 bw.write_buf(&edata)?;
601 } else {
602 bw.write_u32be((edata.len() + 1) as u32)?;
603 bw.write_byte(2)?;
604 bw.write_buf(&edata)?;
605 }
606 } else {
607 bw.write_u32be(0)?;
608 }
609 let end = bw.tell();
610 bw.seek(SeekFrom::Start(start + 12))?;
611 bw.write_u16be((end - start - 4) as u16)?;
612 bw.seek(SeekFrom::Start(end))?;
613
614 Ok(())
615}
616
617fn write_lsd(bw: &mut ByteWriter, stream: &NAStream) -> MuxerResult<()> {
618 if let Some(edata) = stream.get_info().get_extradata() {
619 bw.write_buf(&edata)?;
620 }
621 Ok(())
622}
623
624fn create_interleaver(id: [u8; 4], fcc: [u8; 4], ainfo: NAAudioInfo) -> MuxerResult<Box<dyn Interleaver>> {
625 let frame_size = ainfo.block_len;
626 match &id {
627 b"Int0" => Ok(Box::new(NoInterleaver{ frame_size, pkt: None })),
628 b"Int4" => Ok(Box::new(Int4Interleaver::new(frame_size)?)),
629 b"sipr" => Ok(Box::new(SiproInterleaver::new(frame_size)?)),
f62e2ae0 630 b"genr" => Ok(Box::new(GenericInterleaver::new(ainfo, frame_size, fcc)?)),
9dc1fb4b
KS
631 b"vbrs" | b"vbrf" => Ok(Box::new(AACInterleaver::new(1024))),
632 _ => unimplemented!(),
633 }
634}
635
636pub fn create_audio_stream(stream: &NAStream) -> MuxerResult<Box<dyn RMStreamWriter>> {
637 let info = stream.get_info();
638 let cname = info.get_name();
639 let mut fourcc = [0u8; 4];
640 let mut ileave = [0u8; 4];
641 let mut version = 0;
642 for &(fcc, name, ileaver, cversion) in AUDIO_CODEC_REGISTRY.iter() {
643 if name == cname {
644 fourcc = *fcc;
645 ileave = *ileaver;
646 version = cversion;
647 break;
648 }
649 }
650 if version > 0 {
651 let ainfo = info.get_properties().get_audio_info().unwrap();
652 Ok(Box::new(AudioStreamWriter {
653 fcc: fourcc,
654 il_fcc: ileave,
655 is_raw: &ileave == b"Int0",
656 version,
657 interleave: create_interleaver(ileave, fourcc, ainfo)?,
658 header_pos: 0,
659 data_size: 0,
c5963b17
KS
660 first_time: 0,
661 last_time: 0,
662 size_in: 0,
663 size_out: 0,
9dc1fb4b
KS
664 }))
665 } else {
666 Err(MuxerError::UnsupportedFormat)
667 }
668}
669
670const SIPRO_SWAPS: [[u8; 2]; 38] = [
671 [ 0, 63 ], [ 1, 22 ], [ 2, 44 ], [ 3, 90 ],
672 [ 5, 81 ], [ 7, 31 ], [ 8, 86 ], [ 9, 58 ],
673 [ 10, 36 ], [ 12, 68 ], [ 13, 39 ], [ 14, 73 ],
674 [ 15, 53 ], [ 16, 69 ], [ 17, 57 ], [ 19, 88 ],
675 [ 20, 34 ], [ 21, 71 ], [ 24, 46 ], [ 25, 94 ],
676 [ 26, 54 ], [ 28, 75 ], [ 29, 50 ], [ 32, 70 ],
677 [ 33, 92 ], [ 35, 74 ], [ 38, 85 ], [ 40, 56 ],
678 [ 42, 87 ], [ 43, 65 ], [ 45, 59 ], [ 48, 79 ],
679 [ 49, 93 ], [ 51, 89 ], [ 55, 95 ], [ 61, 76 ],
680 [ 67, 83 ], [ 77, 80 ]
681];
682
f62e2ae0
KS
683macro_rules! int_params {
684 ($rate:expr, $ch:expr, $bsize:expr, $factor:expr, $frm_per_blk:expr) => {
685 InterleaveParams {
686 sample_rate: $rate,
687 channels: $ch,
688 block_size: $bsize,
689 factor: $factor,
690 frames_per_blk: $frm_per_blk,
691 }
692 }
693}
694
9dc1fb4b 695const RA_28_8_INTERLEAVE_PARAMS: &[InterleaveParams] = &[
f62e2ae0 696 int_params!(0, 1, 228, 12, 6)
9dc1fb4b 697];
f62e2ae0
KS
698const SIPRO_INTERLEAVE_PARAMS: &[InterleaveParams] = &[ //2,1,3,0
699 int_params!( 8000, 1, 232, 6, 16),
700 int_params!( 8000, 1, 304, 6, 16),
701 int_params!( 8000, 1, 296, 6, 16),
702 int_params!(16000, 1, 320, 6, 16),
9dc1fb4b
KS
703];
704const ATRAC_INTERLEAVE_PARAMS: &[InterleaveParams] = &[
f62e2ae0
KS
705 int_params!(0, 0, 768, 20, 4),
706 int_params!(0, 0, 1088, 20, 4),
707 int_params!(0, 0, 912, 30, 3),
708 int_params!(0, 0, 1152, 30, 3),
709 int_params!(0, 0, 1272, 30, 3),
710 int_params!(0, 0, 1024, 30, 2),
711 int_params!(0, 0, 768, 10, 1),
712 int_params!(0, 0, 1024, 10, 1),
9dc1fb4b
KS
713];
714const COOK_INTERLEAVE_PARAMS: &[InterleaveParams] = &[
f62e2ae0
KS
715 int_params!( 8000, 1, 288, 8, 9),
716 int_params!(11025, 1, 352, 8, 11),
717 int_params!(22050, 1, 564, 8, 12),
718 int_params!(22050, 1, 600, 9, 10),
719 int_params!(44100, 1, 651, 14, 7),
720 int_params!(44100, 1, 640, 15, 5),
721 int_params!(44100, 1, 744, 20, 4),
722 int_params!(22050, 1, 558, 16, 6),
723 int_params!( 8000, 1, 288, 6, 12),
724 int_params!(11025, 2, 580, 10, 10),
725 int_params!(22050, 2, 564, 14, 6),
726 int_params!(22050, 2, 640, 16, 5),
727 int_params!(44100, 2, 744, 20, 4),
728 int_params!(44100, 2, 834, 30, 3),
729 int_params!(44100, 1, 644, 20, 4),
730 int_params!(44100, 1, 600, 9, 10),
731 int_params!(44100, 1, 651, 14, 7),
732 int_params!(22050, 2, 528, 10, 10),
733 int_params!(22050, 2, 600, 10, 10),
734 int_params!(22050, 2, 600, 10, 10),
735 int_params!(22050, 2, 465, 16, 5),
736 int_params!(44100, 2, 465, 16, 5),
737 int_params!(44100, 2, 640, 16, 5),
738 int_params!(44100, 2, 640, 16, 5),
739 int_params!(44100, 2, 930, 16, 5),
740 int_params!(44100, 2, 1400, 16, 5),
741 int_params!(11025, 2, 376, 8, 11),
742 int_params!(44100, 2, 930, 16, 5),
743 int_params!(44100, 2, 1400, 16, 5),
744 int_params!(22050, 2, 640, 16, 5),
745 int_params!(44100, 5, 1395, 16, 5),
746 int_params!(44100, 6, 1143, 10, 3),
747 int_params!(44100, 6, 1064, 10, 2),
748 int_params!(44100, 6, 778, 1, 1),
9dc1fb4b 749];