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