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