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