fix clippy warnings
[nihav.git] / nihav-realmedia / src / codecs / cook.rs
CommitLineData
5641dccf
KS
1use nihav_core::formats::*;
2use nihav_core::frame::*;
3use nihav_core::codecs::*;
b4d5b851 4use nihav_codec_support::dsp::mdct::IMDCT;
5641dccf
KS
5use nihav_core::io::bitreader::*;
6use nihav_core::io::byteio::{ByteReader, MemoryReader};
7use nihav_core::io::codebook::*;
8use nihav_core::io::intcode::*;
594ca5ca
KS
9use std::f32::consts;
10use std::mem::swap;
38c78f36 11use super::cookdata::*;
594ca5ca
KS
12
13#[derive(Debug,Clone,Copy,PartialEq)]
14enum Mode {
15 Mono,
16 Stereo,
17 JointStereo,
18}
19
20impl Mode {
e07387c7
KS
21 fn get_channels(self) -> usize {
22 match self {
594ca5ca
KS
23 Mode::Mono => 1,
24 _ => 2,
25 }
26 }
27}
28
29struct CookBookReader {
30 bits: &'static [u8],
31 codes: &'static [u16],
32}
33impl CodebookDescReader<u16> for CookBookReader {
34 fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] }
35 fn code(&mut self, idx: usize) -> u32 { self.codes[idx] as u32 }
36 fn sym (&mut self, idx: usize) -> u16 { idx as u16 }
37 fn len(&mut self) -> usize { self.bits.len() }
38}
39
40struct Codebooks {
41 cpl_cb: [Codebook<u16>; 5],
42 quant_cb: Vec<Codebook<u16>>,
43 vq_cb: [Codebook<u16>; 7],
44}
45
46impl Codebooks {
47 fn new() -> Self {
48 let mut cpl0 = CookBookReader { codes: COOK_CPL_2BITS_CODES, bits: COOK_CPL_2BITS_BITS };
49 let mut cpl1 = CookBookReader { codes: COOK_CPL_3BITS_CODES, bits: COOK_CPL_3BITS_BITS };
50 let mut cpl2 = CookBookReader { codes: COOK_CPL_4BITS_CODES, bits: COOK_CPL_4BITS_BITS };
51 let mut cpl3 = CookBookReader { codes: COOK_CPL_5BITS_CODES, bits: COOK_CPL_5BITS_BITS };
52 let mut cpl4 = CookBookReader { codes: COOK_CPL_6BITS_CODES, bits: COOK_CPL_6BITS_BITS };
53 let cpl_cb = [Codebook::new(&mut cpl0, CodebookMode::MSB).unwrap(),
54 Codebook::new(&mut cpl1, CodebookMode::MSB).unwrap(),
55 Codebook::new(&mut cpl2, CodebookMode::MSB).unwrap(),
56 Codebook::new(&mut cpl3, CodebookMode::MSB).unwrap(),
57 Codebook::new(&mut cpl4, CodebookMode::MSB).unwrap()];
58 let mut quant_cb: Vec<Codebook<u16>> = Vec::with_capacity(COOK_QUANT_CODES.len());
59 for i in 0..COOK_QUANT_CODES.len() {
60 let mut quant = CookBookReader { codes: COOK_QUANT_CODES[i], bits: COOK_QUANT_BITS[i] };
61 quant_cb.push(Codebook::new(&mut quant, CodebookMode::MSB).unwrap());
62 }
63 let mut vq0 = CookBookReader { codes: COOK_VQ0_CODES, bits: COOK_VQ0_BITS };
64 let mut vq1 = CookBookReader { codes: COOK_VQ1_CODES, bits: COOK_VQ1_BITS };
65 let mut vq2 = CookBookReader { codes: COOK_VQ2_CODES, bits: COOK_VQ2_BITS };
66 let mut vq3 = CookBookReader { codes: COOK_VQ3_CODES, bits: COOK_VQ3_BITS };
67 let mut vq4 = CookBookReader { codes: COOK_VQ4_CODES, bits: COOK_VQ4_BITS };
68 let mut vq5 = CookBookReader { codes: COOK_VQ5_CODES, bits: COOK_VQ5_BITS };
69 let mut vq6 = CookBookReader { codes: COOK_VQ6_CODES, bits: COOK_VQ6_BITS };
70 let vq_cb = [Codebook::new(&mut vq0, CodebookMode::MSB).unwrap(),
71 Codebook::new(&mut vq1, CodebookMode::MSB).unwrap(),
72 Codebook::new(&mut vq2, CodebookMode::MSB).unwrap(),
73 Codebook::new(&mut vq3, CodebookMode::MSB).unwrap(),
74 Codebook::new(&mut vq4, CodebookMode::MSB).unwrap(),
75 Codebook::new(&mut vq5, CodebookMode::MSB).unwrap(),
76 Codebook::new(&mut vq6, CodebookMode::MSB).unwrap()];
77 Codebooks {
e07387c7
KS
78 cpl_cb,
79 quant_cb,
80 vq_cb,
594ca5ca
KS
81 }
82 }
83}
84
85struct CookDSP {
86 imdct: IMDCT,
87 window: [f32; 1024],
88 out: [f32; 2048],
89 size: usize,
90 pow_tab: [f32; 128],
91 hpow_tab: [f32; 128],
92 gain_tab: [f32; 23],
93}
94
95impl CookDSP {
96 fn new(samples: usize) -> Self {
97 let fsamples = samples as f32;
98 let mut window: [f32; 1024] = [0.0; 1024];
99 let factor = consts::PI / (2.0 * fsamples);
100 let scale = (2.0 / fsamples).sqrt() / 32768.0;
101 for k in 0..samples {
102 window[k] = (factor * ((k as f32) + 0.5)).sin() * scale;
103 }
104 let mut pow_tab: [f32; 128] = [0.0; 128];
105 let mut hpow_tab: [f32; 128] = [0.0; 128];
106 for i in 0..128 {
107 pow_tab[i] = 2.0f32.powf((i as f32) - 64.0);
108 hpow_tab[i] = 2.0f32.powf(((i as f32) - 64.0) * 0.5);
109 }
110 let mut gain_tab: [f32; 23] = [0.0; 23];
111 for i in 0..23 {
112 gain_tab[i] = pow_tab[i + 53].powf(8.0 / fsamples);
113 }
114 let size = samples;
e07387c7 115 CookDSP { imdct: IMDCT::new(samples*2, false), window, out: [0.0; 2048], size, pow_tab, hpow_tab, gain_tab }
594ca5ca
KS
116 }
117}
118
119trait ClipCat {
120 fn clip_cat(&self) -> usize;
121}
122
123impl ClipCat for i32 {
124 fn clip_cat(&self) -> usize { ((*self).max(0) as usize).min(NUM_CATEGORIES - 1) }
125}
126
594ca5ca
KS
127const MAX_SAMPLES: usize = MAX_SUBBANDS * BAND_SIZE;
128const MAX_PAIRS: usize = 5;
594ca5ca
KS
129
130#[derive(Clone,Copy)]
131struct CookChannelPair {
132 start_ch: usize,
133 mode: Mode,
134 samples: usize,
135 subbands: usize,
136 js_start: usize,
137 js_bits: u8,
138 vector_bits: u8,
139
140 decouple: [u8; BAND_SIZE],
141 category: [u8; MAX_SUBBANDS * 2],
142
69f77596 143 block: [[f32; MAX_SAMPLES * 2]; 2],
594ca5ca
KS
144 delay: [[f32; MAX_SAMPLES]; 2],
145 gains: [[i32; 9]; 2],
146 prev_gains: [[i32; 9]; 2],
147 qindex: [i8; MAX_SUBBANDS * 2],
148}
149
150impl CookChannelPair {
151 fn new() -> Self {
152 CookChannelPair {
153 start_ch: 0,
154 mode: Mode::Mono,
155 samples: 0,
156 subbands: 0,
157 js_start: 0,
158 js_bits: 0,
159 vector_bits: 0,
160
161 decouple: [0; BAND_SIZE],
162 category: [0; MAX_SUBBANDS * 2],
163
69f77596 164 block: [[0.0; MAX_SAMPLES * 2]; 2],
594ca5ca
KS
165 delay: [[0.0; MAX_SAMPLES]; 2],
166 gains: [[0; 9]; 2],
167 prev_gains: [[0; 9]; 2],
168 qindex: [0; MAX_SUBBANDS * 2],
169 }
170 }
171 fn read_hdr_v1(&mut self, br: &mut ByteReader) -> DecoderResult<()> {
172 let ver = br.read_u32be()?;
173 let micro_ver = ver & 0xFF;
174 self.samples = br.read_u16be()? as usize;
175 validate!(self.samples > 0 && ((self.samples & (self.samples - 1)) == 0));
176 self.subbands = br.read_u16be()? as usize;
177 validate!(self.subbands <= MAX_SUBBANDS);
178 match micro_ver {
179 1 => {
180 self.mode = Mode::Mono;
181 self.js_start = 0;
182 self.js_bits = 0;
183 },
184 2 => {
185 self.mode = Mode::Stereo;
186 self.js_start = 0;
187 self.js_bits = 0;
188 },
189 3 => {
190 self.mode = Mode::JointStereo;
191 let _delay = br.read_u32be()?;
192 self.js_start = br.read_u16be()? as usize;
193 self.js_bits = br.read_u16be()? as u8;
194 validate!(self.js_start < MAX_SUBBANDS);
195 validate!((self.js_bits >= 2) && (self.js_bits <= 6));
196 },
197 _ => { return Err(DecoderError::InvalidData);}
198 }
199 Ok(())
200 }
201 fn read_hdr_v2(&mut self, br: &mut ByteReader) -> DecoderResult<u32> {
202 let ver = br.read_u32be()?;
203 validate!((ver >> 24) == 2);
204 self.samples = br.read_u16be()? as usize;
205 self.subbands = br.read_u16be()? as usize;
206 validate!(self.subbands <= MAX_SUBBANDS);
207 let _delay = br.read_u32be()?;
208 self.js_start = br.read_u16be()? as usize;
209 validate!(self.js_start < MAX_SUBBANDS);
210 let js_bits = br.read_u16be()?;
211 let chmap = br.read_u32be()?;
212 if chmap.count_ones() == 1 {
213 self.js_bits = 0;
214 self.mode = Mode::Mono;
215 } else {
216 validate!((js_bits >= 2) && (js_bits <= 6));
217 self.js_bits = js_bits as u8;
218 self.mode = Mode::JointStereo;
219 }
220 Ok(chmap)
221 }
222 fn bitalloc(&mut self, num_vectors: usize, bits: usize) {
223 let avail_bits = (if bits > self.samples { self.samples + ((bits - self.samples) * 5) / 8 } else { bits }) as i32;
224 let total_subbands = self.subbands + self.js_start;
225
226 let mut bias: i32 = -32;
227 for i in 0..6 {
228 let mut sum = 0;
229 for j in 0..total_subbands {
230 let idx = ((32 >> i) + bias - (self.qindex[j] as i32)) / 2;
231 sum += COOK_EXP_BITS[idx.clip_cat()];
232 }
233 if sum >= (avail_bits - 32) {
234 bias += 32 >> i;
235 }
236 }
237
238 let mut exp_index1: [usize; MAX_SUBBANDS * 2] = [0; MAX_SUBBANDS * 2];
239 let mut exp_index2: [usize; MAX_SUBBANDS * 2] = [0; MAX_SUBBANDS * 2];
240 let mut sum = 0;
241 for i in 0..total_subbands {
242 let idx = ((bias - (self.qindex[i] as i32)) / 2).clip_cat();
243 sum += COOK_EXP_BITS[idx];
244 exp_index1[i] = idx;
245 exp_index2[i] = idx;
246 }
247
248 let mut tbias1 = sum;
249 let mut tbias2 = sum;
250 let mut tcat: [usize; 128*2] = [0; 128*2];
251 let mut tcat_idx1 = 128;
252 let mut tcat_idx2 = 128;
253 for _ in 1..(1 << self.vector_bits) {
254 if tbias1 + tbias2 > avail_bits * 2 {
255 let mut max = -999999;
256 let mut idx = total_subbands + 1;
257 for j in 0..total_subbands {
258 if exp_index1[j] >= (NUM_CATEGORIES - 1) { continue; }
259 let t = -2 * (exp_index1[j] as i32) - (self.qindex[j] as i32) + bias;
260 if t >= max {
261 max = t;
262 idx = j;
263 }
264 }
265 if idx >= total_subbands { break; }
266 tcat[tcat_idx1] = idx;
267 tcat_idx1 += 1;
268 tbias1 -= COOK_EXP_BITS[exp_index1[idx]] - COOK_EXP_BITS[exp_index1[idx] + 1];
269 exp_index1[idx] += 1;
270 } else {
271 let mut min = 999999;
272 let mut idx = total_subbands + 1;
273 for j in 0..total_subbands {
274 if exp_index2[j] == 0 { continue; }
275 let t = -2 * (exp_index2[j] as i32) - (self.qindex[j] as i32) + bias;
276 if t < min {
277 min = t;
278 idx = j;
279 }
280 }
281 if idx >= total_subbands { break; }
282 tcat_idx2 -= 1;
283 tcat[tcat_idx2] = idx;
284 tbias2 -= COOK_EXP_BITS[exp_index2[idx]] - COOK_EXP_BITS[exp_index2[idx] - 1];
285 exp_index2[idx] -= 1;
286 }
287 }
288 for i in 0..total_subbands {
289 self.category[i] = exp_index2[i] as u8;
290 }
291
292 for _ in 0..num_vectors {
293 let idx = tcat[tcat_idx2];
294 tcat_idx2 += 1;
e6aaad5c 295 self.category[idx] = (self.category[idx] + 1).min((NUM_CATEGORIES - 1) as u8);
594ca5ca
KS
296 }
297 }
298 fn decode_channel_data(&mut self, dsp: &mut CookDSP, rnd: &mut RND, codebooks: &Codebooks, src: &[u8], buf: &mut [u8], channel: usize) -> DecoderResult<()> {
299 // decrypt
300 for (i, b) in src.iter().enumerate() {
301 buf[i] = b ^ COOK_XOR_KEY[i & 3];
302 }
fa90ccfb 303 let mut br = BitReader::new(&buf[..src.len()], BitReaderMode::BE);
594ca5ca
KS
304
305 let num_gains = br.read_code(UintCodeType::UnaryOnes)? as usize;
306 validate!(num_gains <= 8);
307
308 swap(&mut self.gains[channel], &mut self.prev_gains[channel]);
69f77596 309 self.block[channel] = [0.0; MAX_SAMPLES * 2];
594ca5ca
KS
310
311 // gains
312 let mut ipos = 0;
313 for _ in 0..num_gains {
314 let idx = br.read(3)? as usize;
315 let val;
316 if br.read_bool()? {
317 val = (br.read(4)? as i32) - 7;
318 } else {
319 val = -1;
320 }
321 validate!(idx >= ipos);
322 while ipos <= idx {
323 self.prev_gains[channel][ipos] = val;
324 ipos += 1;
325 }
326 }
327 while ipos <= 8 {
328 self.prev_gains[channel][ipos] = 0;
329 ipos += 1;
330 }
331
332 // coupling information
333 if self.mode == Mode::JointStereo {
334 let cstart = COOK_CPL_BAND[self.js_start] as usize;
335 let cend = COOK_CPL_BAND[self.subbands - 1] as usize;
336 if br.read_bool()? {
337 let cb = &codebooks.cpl_cb[(self.js_bits - 2) as usize];
e07387c7 338 for i in cstart..=cend {
594ca5ca
KS
339 self.decouple[i] = br.read_cb(cb)? as u8;
340 }
341 } else {
e07387c7 342 for i in cstart..=cend {
594ca5ca
KS
343 self.decouple[i] = br.read(self.js_bits)? as u8;
344 }
345 }
346 }
347
348 // envelope
349 let tot_subbands = self.subbands + self.js_start;
350 self.qindex[0] = (br.read(6)? as i8) - 6;
351 for i in 1..tot_subbands {
352 let mut pos = i;
353 if pos >= self.js_start * 2 {
354 pos -= self.js_start;
355 } else {
356 pos >>= 1;
357 }
358 let ipos = ((pos as i8) - 1).max(0).min(12);
359 let cb = &codebooks.quant_cb[ipos as usize];
360 self.qindex[i] = (br.read_cb(cb)? as i8) + self.qindex[i - 1] - 12;
361 validate!((self.qindex[i] >= -63) && (self.qindex[i] <= 63));
362 }
363 let num_vectors = br.read(self.vector_bits)? as usize;
364 self.bitalloc(num_vectors, br.left() as usize);
365
366 // coefficients
69f77596 367 self.block[channel] = [0.0; MAX_SAMPLES * 2];
594ca5ca
KS
368 let mut off = 0;
369 for sb in 0..tot_subbands {
370 let mut coef_index: [u8; BAND_SIZE] = [0; BAND_SIZE];
371 let mut coef_sign: [bool; BAND_SIZE] = [false; BAND_SIZE];
372 let cat = self.category[sb] as usize;
373 if (cat < NUM_CATEGORIES - 1) && br.left() > 0 {
374 unpack_band(&mut br, codebooks, &mut coef_index, &mut coef_sign, cat)?;
375 }
376 for i in 0..BAND_SIZE {
377 let val;
378 if coef_index[i] == 0 {
379 let v = COOK_DITHER_TAB[cat];
380 val = if !rnd.get_sign() { v } else { -v };
381 } else {
382 let v = COOK_QUANT_CENTROID[cat][coef_index[i] as usize];
383 val = if !coef_sign[i] { v } else { -v };
384 }
385 self.block[channel][off + i] = val * dsp.hpow_tab[(self.qindex[sb] + 64) as usize];
386 }
387 off += BAND_SIZE;
388 }
389
390 Ok(())
391 }
392 fn decode(&mut self, dsp: &mut CookDSP, rnd: &mut RND, codebooks: &Codebooks, src: &[u8], buf: &mut [u8], abuf: &mut NABufferType) -> DecoderResult<()> {
393 if self.mode == Mode::Stereo {
394 let mut schunk = src.chunks(src.len() / 2);
395 self.decode_channel_data(dsp, rnd, codebooks, schunk.next().unwrap(), buf, 0)?;
396 self.decode_channel_data(dsp, rnd, codebooks, schunk.next().unwrap(), buf, 1)?;
397 } else {
398 self.decode_channel_data(dsp, rnd, codebooks, src, buf, 0)?;
399 }
400 // uncouple joint stereo channels
401 if self.mode == Mode::JointStereo {
402 for i in 0..self.js_start {
403 for j in 0..BAND_SIZE {
404 self.block[1][i * BAND_SIZE + j] = self.block[0][(i * 2 + 1) * BAND_SIZE + j];
405 self.block[0][i * BAND_SIZE + j] = self.block[0][(i * 2) * BAND_SIZE + j];
406 }
407 }
408 let scale_idx = (self.js_bits as usize) - 2;
409 let scale_off = (1 << self.js_bits) as usize;
410 for i in self.js_start..self.subbands {
411 let idx = self.decouple[COOK_CPL_BAND[i] as usize] as usize;
412 let doff = i * BAND_SIZE;
413 let soff = (i + self.js_start) * BAND_SIZE;
414 let m1 = COOK_CPL_SCALES[scale_idx][ 1 + idx];
415 let m2 = COOK_CPL_SCALES[scale_idx][scale_off - 1 - idx];
416 for j in 0..BAND_SIZE {
417 self.block[0][doff + j] = self.block[0][soff + j] * m1;
418 self.block[1][doff + j] = self.block[0][soff + j] * m2;
419 }
420 }
421 for i in (self.subbands * BAND_SIZE)..MAX_SAMPLES {
422 self.block[0][i] = 0.0;
423 self.block[1][i] = 0.0;
424 }
425 self.gains[1] = self.gains[0];
426 self.prev_gains[1] = self.prev_gains[0];
427 }
428 for ch in 0..self.mode.get_channels() {
429 let off = abuf.get_offset(ch + self.start_ch);
430 let mut adata = abuf.get_abuf_f32().unwrap();
1a967e6b 431 let output = adata.get_data_mut().unwrap();
594ca5ca
KS
432 let dst = &mut output[off..];
433
434 dsp.imdct.imdct(&self.block[ch], &mut dsp.out);
435
436 let prev_gain = dsp.pow_tab[(self.prev_gains[ch][0] + 64) as usize];
437 let mut cur_gain = 0.0;
438 let mut cur_gain2 = 0.0;
439 let mut gain_idx = 0;
440 let eighthmask = (self.samples >> 3) - 1;
441 for (i, out) in dst.iter_mut().take(self.samples).enumerate() {
442 *out = dsp.out[i + self.samples] * prev_gain * dsp.window[i]
443 - self.delay[ch][i] * dsp.window[self.samples - i - 1];
444 if (i & eighthmask) == 0 {
445 if (self.gains[ch][gain_idx] == 0) && (self.gains[ch][gain_idx + 1] == 0) {
446 cur_gain = 1.0;
447 cur_gain2 = 1.0;
448 } else {
449 cur_gain = dsp.pow_tab[(self.gains[ch][gain_idx] + 64) as usize];
450 cur_gain2 = dsp.gain_tab[(self.gains[ch][gain_idx + 1] - self.gains[ch][gain_idx] + 11) as usize];
451 }
452 gain_idx += 1;
453 }
454 *out *= cur_gain;
455 cur_gain *= cur_gain2;
456 }
fa57381e 457 self.delay[ch][..self.samples].copy_from_slice(&dsp.out[..self.samples]);
594ca5ca
KS
458 }
459 Ok(())
460 }
461}
462
594ca5ca
KS
463fn unpack_band(br: &mut BitReader, codebooks: &Codebooks, coef_index: &mut [u8; BAND_SIZE], coef_sign: &mut [bool; BAND_SIZE], cat: usize) -> DecoderResult<()> {
464 let cb = &codebooks.vq_cb[cat];
465 let group_size = COOK_VQ_GROUP_SIZE[cat];
466 let mult = COOK_VQ_MULT[cat] + 1;
467 for i in 0..COOK_NUM_VQ_GROUPS[cat] {
468 let ret = br.read_cb(cb);
469 let mut val;
470 if let Ok(v) = ret {
471 val = v as u32;
472 } else {
473 let left = br.left() as u32;
474 br.skip(left)?;
475 break;
476 }
477 let mut nnz = 0;
478 for j in (0..group_size).rev() {
479 let t = (val * COOK_VQ_INV_RADIX[cat]) >> 20;
480 coef_index[i * group_size + j] = (val - t * mult) as u8;
481 if coef_index[i * group_size + j] != 0 {
482 nnz += 1;
483 }
484 val = t;
485 }
486 if (br.left() as usize) < nnz {
487 let left = br.left() as u32;
488 br.skip(left)?;
489 break;
490 }
491 for j in 0..group_size {
492 if coef_index[i * group_size + j] != 0 {
493 coef_sign[i * group_size + j] = br.read_bool()?;
494 } else {
495 coef_sign[i * group_size + j] = false;
496 }
497 }
498 }
499 Ok(())
500}
501
502struct RND {
503 state: u32,
504}
505
506impl RND {
507 fn new() -> Self {
508 Self { state: 0xC0DECC00 }
509 }
510 fn get_sign(&mut self) -> bool {
511 self.state = (self.state & 0xFFFF).wrapping_mul(36969).wrapping_add(self.state >> 16);
512 (self.state & 0x10000) != 0
513 }
514}
515
516struct CookDecoder {
2422d969 517 info: NACodecInfoRef,
594ca5ca
KS
518 chmap: NAChannelMap,
519 src: [u8; 65536],
520 num_pairs: usize,
521 pairs: [CookChannelPair; MAX_PAIRS],
522 channels: usize,
523 samples: usize,
524 codebooks: Codebooks,
525 rnd: RND,
526 dsp: CookDSP,
527}
528
529impl CookDecoder {
530 fn new() -> Self {
531 CookDecoder {
532 info: NACodecInfo::new_dummy(),
533 chmap: NAChannelMap::new(),
534 src: [0; 65536],
535 num_pairs: 0,
536 channels: 0,
537 samples: 0,
538 pairs: [CookChannelPair::new(); MAX_PAIRS],
539 codebooks: Codebooks::new(),
540 rnd: RND::new(),
541 dsp: CookDSP::new(1024),
542 }
543 }
544}
545
546impl NADecoder for CookDecoder {
01613464 547 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
594ca5ca
KS
548 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
549 let edata = info.get_extradata().unwrap();
550 validate!(edata.len() >= 4);
551
552 let mut mr = MemoryReader::new_read(&edata);
553 let mut br = ByteReader::new(&mut mr);
554 let ver = br.peek_u32be()?;
555
556 let maj_ver = ver >> 24;
557 let mut chmap: u32 = 0;
558 match maj_ver {
559 1 => {
560 self.num_pairs = 1;
561 self.pairs[0].read_hdr_v1(&mut br)?;
562 self.channels = self.pairs[0].mode.get_channels();
563 if ainfo.get_channels() == 1 { // forced mono
b7eda71d 564 self.pairs[0].mode = Mode::Mono;
594ca5ca
KS
565 self.channels = 1;
566 chmap = 0x4;
567 } else {
568 chmap = 0x3;
569 }
570 },
571 2 => {
572 self.num_pairs = (edata.len() - (br.tell() as usize)) / 20;
573 validate!(self.num_pairs <= MAX_PAIRS);
574 let mut start_ch = 0;
575 for i in 0..self.num_pairs {
576 let pair_chmap = self.pairs[i].read_hdr_v2(&mut br)?;
577 self.pairs[i].start_ch = start_ch;
578 validate!((chmap & pair_chmap) == 0);
1ef35f7d 579 chmap |= pair_chmap;
594ca5ca
KS
580 start_ch += self.pairs[i].mode.get_channels();
581 }
582 self.channels = start_ch;
583 },
584 _ => { return Err(DecoderError::InvalidData); }
585 };
586
587 self.samples = self.pairs[0].samples / self.pairs[0].mode.get_channels();
588 validate!((self.samples >= 16) && (self.samples <= 1024));
589 if self.samples != self.dsp.size {
590 self.dsp = CookDSP::new(self.samples);
591 }
592 self.chmap = NAChannelMap::from_ms_mapping(chmap);
593
594 for i in 1..self.num_pairs {
595 validate!((self.pairs[i].samples / self.pairs[i].mode.get_channels()) == self.samples);
596 }
597
598 let vector_bits = match self.samples {
599 16 | 32 | 64 | 128 | 256 => 5,
600 512 => 6,
601 1024 => 7,
602 _ => unreachable!(),
603 };
604 for pair in self.pairs.iter_mut() {
605 match pair.mode {
606 Mode::Mono => {
607 pair.vector_bits = 5;
608 },
609 Mode::Stereo => {
610 pair.vector_bits = 5;
611 pair.samples >>= 1;
612 },
613 Mode::JointStereo => {
614 pair.vector_bits = vector_bits;
615 pair.samples >>= 1;
616 },
617 };
618 }
619
620 let ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), self.channels as u8,
621 SND_F32P_FORMAT, self.samples);
622 self.info = info.replace_info(NACodecTypeInfo::Audio(ainfo));
623
624 Ok(())
625 } else {
626 Err(DecoderError::InvalidData)
627 }
628 }
01613464 629 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
594ca5ca
KS
630 let info = pkt.get_stream().get_info();
631 validate!(info.get_properties().is_audio());
632 let pktbuf = pkt.get_buffer();
633 validate!(pktbuf.len() > self.num_pairs * 2);
634
635 let mut seg_size: [usize; MAX_PAIRS] = [0; MAX_PAIRS];
636 let mut seg_start: [usize; MAX_PAIRS+1] = [0; MAX_PAIRS+1];
637
638 let ainfo = self.info.get_properties().get_audio_info().unwrap();
639
640 seg_size[0] = pktbuf.len() - (self.num_pairs - 1);
641 for i in 1..self.num_pairs {
642 seg_size[i] = (pktbuf[pktbuf.len() - self.num_pairs + i] as usize) * 2;
643 validate!(seg_size[i] != 0);
644 let ret = seg_size[0].checked_sub(seg_size[i]);
645 if let Some(val) = ret {
646 seg_size[0] = val;
647 } else {
648 return Err(DecoderError::InvalidData);
649 }
650 }
651 validate!(seg_size[0] != 0);
652 seg_start[0] = 0;
653 for i in 0..self.num_pairs {
654 seg_start[i + 1] = seg_start[i] + seg_size[i];
655 }
656
657 let mut abuf = alloc_audio_buffer(ainfo, self.samples, self.chmap.clone())?;
658
659 for pair in 0..self.num_pairs {
660 self.pairs[pair].decode(&mut self.dsp, &mut self.rnd, &self.codebooks, &pktbuf[seg_start[pair]..seg_start[pair + 1]], &mut self.src, &mut abuf)?;
661 }
662
663 let mut frm = NAFrame::new_from_pkt(pkt, self.info.replace_info(NACodecTypeInfo::Audio(ainfo)), abuf);
664 frm.set_keyframe(true);
171860fc 665 Ok(frm.into_ref())
594ca5ca 666 }
f9be4e75
KS
667 fn flush(&mut self) {
668 for pair in self.pairs.iter_mut() {
669 pair.delay = [[0.0; MAX_SAMPLES]; 2];
670 }
671 }
594ca5ca
KS
672}
673
7d57ae2f
KS
674impl NAOptionHandler for CookDecoder {
675 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
676 fn set_options(&mut self, _options: &[NAOption]) { }
677 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
678}
679
08a1fab7 680pub fn get_decoder() -> Box<dyn NADecoder + Send> {
594ca5ca
KS
681 Box::new(CookDecoder::new())
682}
683
684#[cfg(test)]
685mod test {
3167c45c
KS
686 use nihav_core::codecs::RegisteredDecoders;
687 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 688 use nihav_codec_support::test::dec_video::*;
78fb6560 689 use crate::realmedia_register_all_decoders;
e64739f8 690 use crate::realmedia_register_all_demuxers;
594ca5ca
KS
691 #[test]
692 fn test_cook() {
3167c45c
KS
693 let mut dmx_reg = RegisteredDemuxers::new();
694 realmedia_register_all_demuxers(&mut dmx_reg);
695 let mut dec_reg = RegisteredDecoders::new();
78fb6560 696 realmedia_register_all_decoders(&mut dec_reg);
3167c45c 697
594ca5ca 698// let file = "assets/RV/rv30_weighted_mc.rm";
886cde48 699 // sample: https://samples.mplayerhq.hu/real/AC-cook/cook_5.1/multichannel.rma
594ca5ca 700 let file = "assets/RV/multichannel.rma";
5580b11b 701 test_decode_audio("realmedia", file, Some(2000), None/*Some("cook")*/, &dmx_reg, &dec_reg);
594ca5ca
KS
702 }
703}