]> git.nihav.org Git - nihav.git/blame - nihav-realmedia/src/codecs/cook.rs
avimux: do not record palette change chunks in OpenDML index
[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;
d92111a8
KS
101 for (k, el) in window[..samples].iter_mut().enumerate() {
102 *el = (factor * ((k as f32) + 0.5)).sin() * scale;
594ca5ca
KS
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 {
d92111a8 216 validate!((2..=6).contains(&js_bits));
594ca5ca
KS
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;
d92111a8
KS
257 for (j, (&exp_idx, &q_idx)) in exp_index1.iter()
258 .zip(self.qindex.iter()).enumerate().take(total_subbands) {
259 if exp_idx >= (NUM_CATEGORIES - 1) { continue; }
260 let t = -2 * (exp_idx as i32) - (q_idx as i32) + bias;
594ca5ca
KS
261 if t >= max {
262 max = t;
263 idx = j;
264 }
265 }
266 if idx >= total_subbands { break; }
267 tcat[tcat_idx1] = idx;
268 tcat_idx1 += 1;
269 tbias1 -= COOK_EXP_BITS[exp_index1[idx]] - COOK_EXP_BITS[exp_index1[idx] + 1];
270 exp_index1[idx] += 1;
271 } else {
272 let mut min = 999999;
273 let mut idx = total_subbands + 1;
d92111a8
KS
274 for (j, (&exp_idx, &q_idx)) in exp_index2.iter()
275 .zip(self.qindex.iter()).enumerate().take(total_subbands) {
276 if exp_idx == 0 { continue; }
277 let t = -2 * (exp_idx as i32) - (q_idx as i32) + bias;
594ca5ca
KS
278 if t < min {
279 min = t;
280 idx = j;
281 }
282 }
283 if idx >= total_subbands { break; }
284 tcat_idx2 -= 1;
285 tcat[tcat_idx2] = idx;
286 tbias2 -= COOK_EXP_BITS[exp_index2[idx]] - COOK_EXP_BITS[exp_index2[idx] - 1];
287 exp_index2[idx] -= 1;
288 }
289 }
d92111a8
KS
290 for (cat, &exp_idx) in self.category.iter_mut().zip(exp_index2.iter()).take(total_subbands) {
291 *cat = exp_idx as u8;
594ca5ca
KS
292 }
293
294 for _ in 0..num_vectors {
295 let idx = tcat[tcat_idx2];
296 tcat_idx2 += 1;
e6aaad5c 297 self.category[idx] = (self.category[idx] + 1).min((NUM_CATEGORIES - 1) as u8);
594ca5ca
KS
298 }
299 }
300 fn decode_channel_data(&mut self, dsp: &mut CookDSP, rnd: &mut RND, codebooks: &Codebooks, src: &[u8], buf: &mut [u8], channel: usize) -> DecoderResult<()> {
301 // decrypt
302 for (i, b) in src.iter().enumerate() {
303 buf[i] = b ^ COOK_XOR_KEY[i & 3];
304 }
fa90ccfb 305 let mut br = BitReader::new(&buf[..src.len()], BitReaderMode::BE);
594ca5ca
KS
306
307 let num_gains = br.read_code(UintCodeType::UnaryOnes)? as usize;
308 validate!(num_gains <= 8);
309
310 swap(&mut self.gains[channel], &mut self.prev_gains[channel]);
69f77596 311 self.block[channel] = [0.0; MAX_SAMPLES * 2];
594ca5ca
KS
312
313 // gains
314 let mut ipos = 0;
315 for _ in 0..num_gains {
316 let idx = br.read(3)? as usize;
d92111a8
KS
317 let val = if br.read_bool()? {
318 (br.read(4)? as i32) - 7
319 } else {
320 -1
321 };
594ca5ca
KS
322 validate!(idx >= ipos);
323 while ipos <= idx {
324 self.prev_gains[channel][ipos] = val;
325 ipos += 1;
326 }
327 }
328 while ipos <= 8 {
329 self.prev_gains[channel][ipos] = 0;
330 ipos += 1;
331 }
332
333 // coupling information
334 if self.mode == Mode::JointStereo {
335 let cstart = COOK_CPL_BAND[self.js_start] as usize;
336 let cend = COOK_CPL_BAND[self.subbands - 1] as usize;
337 if br.read_bool()? {
338 let cb = &codebooks.cpl_cb[(self.js_bits - 2) as usize];
e07387c7 339 for i in cstart..=cend {
594ca5ca
KS
340 self.decouple[i] = br.read_cb(cb)? as u8;
341 }
342 } else {
e07387c7 343 for i in cstart..=cend {
594ca5ca
KS
344 self.decouple[i] = br.read(self.js_bits)? as u8;
345 }
346 }
347 }
348
349 // envelope
350 let tot_subbands = self.subbands + self.js_start;
351 self.qindex[0] = (br.read(6)? as i8) - 6;
352 for i in 1..tot_subbands {
353 let mut pos = i;
354 if pos >= self.js_start * 2 {
355 pos -= self.js_start;
356 } else {
357 pos >>= 1;
358 }
359 let ipos = ((pos as i8) - 1).max(0).min(12);
360 let cb = &codebooks.quant_cb[ipos as usize];
361 self.qindex[i] = (br.read_cb(cb)? as i8) + self.qindex[i - 1] - 12;
362 validate!((self.qindex[i] >= -63) && (self.qindex[i] <= 63));
363 }
364 let num_vectors = br.read(self.vector_bits)? as usize;
365 self.bitalloc(num_vectors, br.left() as usize);
366
367 // coefficients
69f77596 368 self.block[channel] = [0.0; MAX_SAMPLES * 2];
594ca5ca
KS
369 let mut off = 0;
370 for sb in 0..tot_subbands {
371 let mut coef_index: [u8; BAND_SIZE] = [0; BAND_SIZE];
372 let mut coef_sign: [bool; BAND_SIZE] = [false; BAND_SIZE];
373 let cat = self.category[sb] as usize;
374 if (cat < NUM_CATEGORIES - 1) && br.left() > 0 {
375 unpack_band(&mut br, codebooks, &mut coef_index, &mut coef_sign, cat)?;
376 }
377 for i in 0..BAND_SIZE {
d92111a8
KS
378 let val = if coef_index[i] == 0 {
379 let v = COOK_DITHER_TAB[cat];
380 if !rnd.get_sign() { v } else { -v }
381 } else {
382 let v = COOK_QUANT_CENTROID[cat][coef_index[i] as usize];
383 if !coef_sign[i] { v } else { -v }
384 };
594ca5ca
KS
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 }
d92111a8 392 #[allow(clippy::needless_range_loop)]
594ca5ca
KS
393 fn decode(&mut self, dsp: &mut CookDSP, rnd: &mut RND, codebooks: &Codebooks, src: &[u8], buf: &mut [u8], abuf: &mut NABufferType) -> DecoderResult<()> {
394 if self.mode == Mode::Stereo {
395 let mut schunk = src.chunks(src.len() / 2);
396 self.decode_channel_data(dsp, rnd, codebooks, schunk.next().unwrap(), buf, 0)?;
397 self.decode_channel_data(dsp, rnd, codebooks, schunk.next().unwrap(), buf, 1)?;
398 } else {
399 self.decode_channel_data(dsp, rnd, codebooks, src, buf, 0)?;
400 }
401 // uncouple joint stereo channels
402 if self.mode == Mode::JointStereo {
403 for i in 0..self.js_start {
404 for j in 0..BAND_SIZE {
405 self.block[1][i * BAND_SIZE + j] = self.block[0][(i * 2 + 1) * BAND_SIZE + j];
406 self.block[0][i * BAND_SIZE + j] = self.block[0][(i * 2) * BAND_SIZE + j];
407 }
408 }
409 let scale_idx = (self.js_bits as usize) - 2;
410 let scale_off = (1 << self.js_bits) as usize;
411 for i in self.js_start..self.subbands {
412 let idx = self.decouple[COOK_CPL_BAND[i] as usize] as usize;
413 let doff = i * BAND_SIZE;
414 let soff = (i + self.js_start) * BAND_SIZE;
415 let m1 = COOK_CPL_SCALES[scale_idx][ 1 + idx];
416 let m2 = COOK_CPL_SCALES[scale_idx][scale_off - 1 - idx];
417 for j in 0..BAND_SIZE {
418 self.block[0][doff + j] = self.block[0][soff + j] * m1;
419 self.block[1][doff + j] = self.block[0][soff + j] * m2;
420 }
421 }
422 for i in (self.subbands * BAND_SIZE)..MAX_SAMPLES {
423 self.block[0][i] = 0.0;
424 self.block[1][i] = 0.0;
425 }
426 self.gains[1] = self.gains[0];
427 self.prev_gains[1] = self.prev_gains[0];
428 }
429 for ch in 0..self.mode.get_channels() {
430 let off = abuf.get_offset(ch + self.start_ch);
431 let mut adata = abuf.get_abuf_f32().unwrap();
1a967e6b 432 let output = adata.get_data_mut().unwrap();
594ca5ca
KS
433 let dst = &mut output[off..];
434
435 dsp.imdct.imdct(&self.block[ch], &mut dsp.out);
436
437 let prev_gain = dsp.pow_tab[(self.prev_gains[ch][0] + 64) as usize];
438 let mut cur_gain = 0.0;
439 let mut cur_gain2 = 0.0;
440 let mut gain_idx = 0;
441 let eighthmask = (self.samples >> 3) - 1;
442 for (i, out) in dst.iter_mut().take(self.samples).enumerate() {
443 *out = dsp.out[i + self.samples] * prev_gain * dsp.window[i]
444 - self.delay[ch][i] * dsp.window[self.samples - i - 1];
445 if (i & eighthmask) == 0 {
446 if (self.gains[ch][gain_idx] == 0) && (self.gains[ch][gain_idx + 1] == 0) {
447 cur_gain = 1.0;
448 cur_gain2 = 1.0;
449 } else {
450 cur_gain = dsp.pow_tab[(self.gains[ch][gain_idx] + 64) as usize];
451 cur_gain2 = dsp.gain_tab[(self.gains[ch][gain_idx + 1] - self.gains[ch][gain_idx] + 11) as usize];
452 }
453 gain_idx += 1;
454 }
455 *out *= cur_gain;
456 cur_gain *= cur_gain2;
457 }
fa57381e 458 self.delay[ch][..self.samples].copy_from_slice(&dsp.out[..self.samples]);
594ca5ca
KS
459 }
460 Ok(())
461 }
462}
463
594ca5ca
KS
464fn unpack_band(br: &mut BitReader, codebooks: &Codebooks, coef_index: &mut [u8; BAND_SIZE], coef_sign: &mut [bool; BAND_SIZE], cat: usize) -> DecoderResult<()> {
465 let cb = &codebooks.vq_cb[cat];
466 let group_size = COOK_VQ_GROUP_SIZE[cat];
467 let mult = COOK_VQ_MULT[cat] + 1;
468 for i in 0..COOK_NUM_VQ_GROUPS[cat] {
469 let ret = br.read_cb(cb);
470 let mut val;
471 if let Ok(v) = ret {
472 val = v as u32;
473 } else {
474 let left = br.left() as u32;
475 br.skip(left)?;
476 break;
477 }
478 let mut nnz = 0;
479 for j in (0..group_size).rev() {
480 let t = (val * COOK_VQ_INV_RADIX[cat]) >> 20;
481 coef_index[i * group_size + j] = (val - t * mult) as u8;
482 if coef_index[i * group_size + j] != 0 {
483 nnz += 1;
484 }
485 val = t;
486 }
487 if (br.left() as usize) < nnz {
488 let left = br.left() as u32;
489 br.skip(left)?;
490 break;
491 }
492 for j in 0..group_size {
493 if coef_index[i * group_size + j] != 0 {
494 coef_sign[i * group_size + j] = br.read_bool()?;
495 } else {
496 coef_sign[i * group_size + j] = false;
497 }
498 }
499 }
500 Ok(())
501}
502
503struct RND {
504 state: u32,
505}
506
507impl RND {
508 fn new() -> Self {
509 Self { state: 0xC0DECC00 }
510 }
511 fn get_sign(&mut self) -> bool {
512 self.state = (self.state & 0xFFFF).wrapping_mul(36969).wrapping_add(self.state >> 16);
513 (self.state & 0x10000) != 0
514 }
515}
516
517struct CookDecoder {
2422d969 518 info: NACodecInfoRef,
594ca5ca
KS
519 chmap: NAChannelMap,
520 src: [u8; 65536],
521 num_pairs: usize,
522 pairs: [CookChannelPair; MAX_PAIRS],
523 channels: usize,
524 samples: usize,
525 codebooks: Codebooks,
526 rnd: RND,
527 dsp: CookDSP,
528}
529
530impl CookDecoder {
531 fn new() -> Self {
532 CookDecoder {
533 info: NACodecInfo::new_dummy(),
534 chmap: NAChannelMap::new(),
535 src: [0; 65536],
536 num_pairs: 0,
537 channels: 0,
538 samples: 0,
539 pairs: [CookChannelPair::new(); MAX_PAIRS],
540 codebooks: Codebooks::new(),
541 rnd: RND::new(),
542 dsp: CookDSP::new(1024),
543 }
544 }
545}
546
547impl NADecoder for CookDecoder {
01613464 548 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
594ca5ca
KS
549 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
550 let edata = info.get_extradata().unwrap();
551 validate!(edata.len() >= 4);
552
553 let mut mr = MemoryReader::new_read(&edata);
554 let mut br = ByteReader::new(&mut mr);
555 let ver = br.peek_u32be()?;
556
557 let maj_ver = ver >> 24;
558 let mut chmap: u32 = 0;
559 match maj_ver {
560 1 => {
561 self.num_pairs = 1;
562 self.pairs[0].read_hdr_v1(&mut br)?;
563 self.channels = self.pairs[0].mode.get_channels();
564 if ainfo.get_channels() == 1 { // forced mono
b7eda71d 565 self.pairs[0].mode = Mode::Mono;
594ca5ca
KS
566 self.channels = 1;
567 chmap = 0x4;
568 } else {
569 chmap = 0x3;
570 }
571 },
572 2 => {
573 self.num_pairs = (edata.len() - (br.tell() as usize)) / 20;
574 validate!(self.num_pairs <= MAX_PAIRS);
575 let mut start_ch = 0;
576 for i in 0..self.num_pairs {
577 let pair_chmap = self.pairs[i].read_hdr_v2(&mut br)?;
578 self.pairs[i].start_ch = start_ch;
579 validate!((chmap & pair_chmap) == 0);
1ef35f7d 580 chmap |= pair_chmap;
594ca5ca
KS
581 start_ch += self.pairs[i].mode.get_channels();
582 }
583 self.channels = start_ch;
584 },
585 _ => { return Err(DecoderError::InvalidData); }
586 };
587
588 self.samples = self.pairs[0].samples / self.pairs[0].mode.get_channels();
589 validate!((self.samples >= 16) && (self.samples <= 1024));
590 if self.samples != self.dsp.size {
591 self.dsp = CookDSP::new(self.samples);
592 }
593 self.chmap = NAChannelMap::from_ms_mapping(chmap);
594
595 for i in 1..self.num_pairs {
596 validate!((self.pairs[i].samples / self.pairs[i].mode.get_channels()) == self.samples);
597 }
598
599 let vector_bits = match self.samples {
600 16 | 32 | 64 | 128 | 256 => 5,
601 512 => 6,
602 1024 => 7,
603 _ => unreachable!(),
604 };
605 for pair in self.pairs.iter_mut() {
606 match pair.mode {
607 Mode::Mono => {
608 pair.vector_bits = 5;
609 },
610 Mode::Stereo => {
611 pair.vector_bits = 5;
612 pair.samples >>= 1;
613 },
614 Mode::JointStereo => {
615 pair.vector_bits = vector_bits;
616 pair.samples >>= 1;
617 },
618 };
619 }
620
621 let ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), self.channels as u8,
622 SND_F32P_FORMAT, self.samples);
623 self.info = info.replace_info(NACodecTypeInfo::Audio(ainfo));
624
625 Ok(())
626 } else {
627 Err(DecoderError::InvalidData)
628 }
629 }
01613464 630 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
594ca5ca
KS
631 let info = pkt.get_stream().get_info();
632 validate!(info.get_properties().is_audio());
633 let pktbuf = pkt.get_buffer();
634 validate!(pktbuf.len() > self.num_pairs * 2);
635
636 let mut seg_size: [usize; MAX_PAIRS] = [0; MAX_PAIRS];
637 let mut seg_start: [usize; MAX_PAIRS+1] = [0; MAX_PAIRS+1];
638
639 let ainfo = self.info.get_properties().get_audio_info().unwrap();
640
641 seg_size[0] = pktbuf.len() - (self.num_pairs - 1);
642 for i in 1..self.num_pairs {
643 seg_size[i] = (pktbuf[pktbuf.len() - self.num_pairs + i] as usize) * 2;
644 validate!(seg_size[i] != 0);
645 let ret = seg_size[0].checked_sub(seg_size[i]);
646 if let Some(val) = ret {
647 seg_size[0] = val;
648 } else {
649 return Err(DecoderError::InvalidData);
650 }
651 }
652 validate!(seg_size[0] != 0);
653 seg_start[0] = 0;
654 for i in 0..self.num_pairs {
655 seg_start[i + 1] = seg_start[i] + seg_size[i];
656 }
657
658 let mut abuf = alloc_audio_buffer(ainfo, self.samples, self.chmap.clone())?;
659
660 for pair in 0..self.num_pairs {
661 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)?;
662 }
663
664 let mut frm = NAFrame::new_from_pkt(pkt, self.info.replace_info(NACodecTypeInfo::Audio(ainfo)), abuf);
665 frm.set_keyframe(true);
171860fc 666 Ok(frm.into_ref())
594ca5ca 667 }
f9be4e75
KS
668 fn flush(&mut self) {
669 for pair in self.pairs.iter_mut() {
670 pair.delay = [[0.0; MAX_SAMPLES]; 2];
671 }
672 }
594ca5ca
KS
673}
674
7d57ae2f
KS
675impl NAOptionHandler for CookDecoder {
676 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
677 fn set_options(&mut self, _options: &[NAOption]) { }
678 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
679}
680
08a1fab7 681pub fn get_decoder() -> Box<dyn NADecoder + Send> {
594ca5ca
KS
682 Box::new(CookDecoder::new())
683}
684
685#[cfg(test)]
686mod test {
3167c45c
KS
687 use nihav_core::codecs::RegisteredDecoders;
688 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 689 use nihav_codec_support::test::dec_video::*;
78fb6560 690 use crate::realmedia_register_all_decoders;
e64739f8 691 use crate::realmedia_register_all_demuxers;
594ca5ca
KS
692 #[test]
693 fn test_cook() {
3167c45c
KS
694 let mut dmx_reg = RegisteredDemuxers::new();
695 realmedia_register_all_demuxers(&mut dmx_reg);
696 let mut dec_reg = RegisteredDecoders::new();
78fb6560 697 realmedia_register_all_decoders(&mut dec_reg);
3167c45c 698
594ca5ca 699// let file = "assets/RV/rv30_weighted_mc.rm";
886cde48 700 // sample: https://samples.mplayerhq.hu/real/AC-cook/cook_5.1/multichannel.rma
594ca5ca 701 let file = "assets/RV/multichannel.rma";
5580b11b 702 test_decode_audio("realmedia", file, Some(2000), None/*Some("cook")*/, &dmx_reg, &dec_reg);
594ca5ca
KS
703 }
704}