Mercurial > libavcodec.hg
annotate cook.c @ 3990:746a60ba3177 libavcodec
enable CMOV_IS_FAST as its faster or equal speed on every cpu (duron, athlon, PM, P3) from which ive seen benchmarks, it might be slower on P4 but noone has posted benchmarks ...
author | michael |
---|---|
date | Wed, 11 Oct 2006 12:23:40 +0000 |
parents | c8c591fe26f8 |
children | a0f83004d485 |
rev | line source |
---|---|
2956 | 1 /* |
2 * COOK compatible decoder | |
3 * Copyright (c) 2003 Sascha Sommer | |
4 * Copyright (c) 2005 Benjamin Larsson | |
5 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3619
diff
changeset
|
6 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3619
diff
changeset
|
7 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3619
diff
changeset
|
8 * FFmpeg is free software; you can redistribute it and/or |
2956 | 9 * modify it under the terms of the GNU Lesser General Public |
10 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3619
diff
changeset
|
11 * version 2.1 of the License, or (at your option) any later version. |
2956 | 12 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3619
diff
changeset
|
13 * FFmpeg is distributed in the hope that it will be useful, |
2956 | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3619
diff
changeset
|
19 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
3019
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2956 | 21 * |
22 */ | |
23 | |
24 /** | |
25 * @file cook.c | |
26 * Cook compatible decoder. | |
27 * This decoder handles RealNetworks, RealAudio G2 data. | |
28 * Cook is identified by the codec name cook in RM files. | |
29 * | |
30 * To use this decoder, a calling application must supply the extradata | |
31 * bytes provided from the RM container; 8+ bytes for mono streams and | |
32 * 16+ for stereo streams (maybe more). | |
33 * | |
34 * Codec technicalities (all this assume a buffer length of 1024): | |
35 * Cook works with several different techniques to achieve its compression. | |
36 * In the timedomain the buffer is divided into 8 pieces and quantized. If | |
37 * two neighboring pieces have different quantization index a smooth | |
38 * quantization curve is used to get a smooth overlap between the different | |
39 * pieces. | |
40 * To get to the transformdomain Cook uses a modulated lapped transform. | |
41 * The transform domain has 50 subbands with 20 elements each. This | |
42 * means only a maximum of 50*20=1000 coefficients are used out of the 1024 | |
43 * available. | |
44 */ | |
45 | |
46 #include <math.h> | |
47 #include <stddef.h> | |
48 #include <stdio.h> | |
49 | |
50 #include "avcodec.h" | |
51 #include "bitstream.h" | |
52 #include "dsputil.h" | |
53 | |
54 #include "cookdata.h" | |
55 | |
56 /* the different Cook versions */ | |
57 #define MONO_COOK1 0x1000001 | |
58 #define MONO_COOK2 0x1000002 | |
59 #define JOINT_STEREO 0x1000003 | |
60 #define MC_COOK 0x2000000 //multichannel Cook, not supported | |
61 | |
62 #define SUBBAND_SIZE 20 | |
63 //#define COOKDEBUG | |
64 | |
65 typedef struct { | |
66 int size; | |
67 int qidx_table1[8]; | |
68 int qidx_table2[8]; | |
69 } COOKgain; | |
70 | |
71 typedef struct __attribute__((__packed__)){ | |
72 /* codec data start */ | |
73 uint32_t cookversion; //in network order, bigendian | |
74 uint16_t samples_per_frame; //amount of samples per frame per channel, bigendian | |
75 uint16_t subbands; //amount of bands used in the frequency domain, bigendian | |
76 /* Mono extradata ends here. */ | |
77 uint32_t unused; | |
78 uint16_t js_subband_start; //bigendian | |
79 uint16_t js_vlc_bits; //bigendian | |
80 /* Stereo extradata ends here. */ | |
81 } COOKextradata; | |
82 | |
83 | |
84 typedef struct { | |
85 GetBitContext gb; | |
86 /* stream data */ | |
87 int nb_channels; | |
88 int joint_stereo; | |
89 int bit_rate; | |
90 int sample_rate; | |
91 int samples_per_channel; | |
92 int samples_per_frame; | |
93 int subbands; | |
3090 | 94 int log2_numvector_size; |
95 int numvector_size; //1 << log2_numvector_size; | |
2956 | 96 int js_subband_start; |
97 int total_subbands; | |
98 int num_vectors; | |
99 int bits_per_subpacket; | |
100 /* states */ | |
101 int random_state; | |
102 | |
103 /* transform data */ | |
104 FFTContext fft_ctx; | |
105 FFTSample mlt_tmp[1024] __attribute__((aligned(16))); /* temporary storage for imlt */ | |
106 float* mlt_window; | |
107 float* mlt_precos; | |
108 float* mlt_presin; | |
109 float* mlt_postcos; | |
110 int fft_size; | |
111 int fft_order; | |
112 int mlt_size; //modulated lapped transform size | |
113 | |
114 /* gain buffers */ | |
115 COOKgain* gain_now_ptr; | |
116 COOKgain* gain_previous_ptr; | |
117 COOKgain gain_current; | |
118 COOKgain gain_now; | |
119 COOKgain gain_previous; | |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
120 COOKgain gain_channel1[2]; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
121 COOKgain gain_channel2[2]; |
2956 | 122 |
123 /* VLC data */ | |
124 int js_vlc_bits; | |
125 VLC envelope_quant_index[13]; | |
126 VLC sqvh[7]; //scalar quantization | |
127 VLC ccpl; //channel coupling | |
128 | |
129 /* generatable tables and related variables */ | |
130 int gain_size_factor; | |
131 float gain_table[23]; | |
132 float pow2tab[127]; | |
133 float rootpow2tab[127]; | |
134 | |
135 /* data buffers */ | |
136 | |
137 uint8_t* decoded_bytes_buffer; | |
138 float mono_mdct_output[2048] __attribute__((aligned(16))); | |
139 float* previous_buffer_ptr[2]; | |
140 float mono_previous_buffer1[1024]; | |
141 float mono_previous_buffer2[1024]; | |
142 float* decode_buf_ptr[4]; | |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
143 float* decode_buf_ptr2[2]; |
2956 | 144 float decode_buffer_1[1024]; |
145 float decode_buffer_2[1024]; | |
146 float decode_buffer_3[1024]; | |
147 float decode_buffer_4[1024]; | |
148 } COOKContext; | |
149 | |
150 /* debug functions */ | |
151 | |
152 #ifdef COOKDEBUG | |
153 static void dump_float_table(float* table, int size, int delimiter) { | |
154 int i=0; | |
155 av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i); | |
156 for (i=0 ; i<size ; i++) { | |
157 av_log(NULL, AV_LOG_ERROR, "%5.1f, ", table[i]); | |
158 if ((i+1)%delimiter == 0) av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i+1); | |
159 } | |
160 } | |
161 | |
162 static void dump_int_table(int* table, int size, int delimiter) { | |
163 int i=0; | |
164 av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i); | |
165 for (i=0 ; i<size ; i++) { | |
166 av_log(NULL, AV_LOG_ERROR, "%d, ", table[i]); | |
167 if ((i+1)%delimiter == 0) av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i+1); | |
168 } | |
169 } | |
170 | |
171 static void dump_short_table(short* table, int size, int delimiter) { | |
172 int i=0; | |
173 av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i); | |
174 for (i=0 ; i<size ; i++) { | |
175 av_log(NULL, AV_LOG_ERROR, "%d, ", table[i]); | |
176 if ((i+1)%delimiter == 0) av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i+1); | |
177 } | |
178 } | |
179 | |
180 #endif | |
181 | |
182 /*************** init functions ***************/ | |
183 | |
184 /* table generator */ | |
185 static void init_pow2table(COOKContext *q){ | |
186 int i; | |
187 q->pow2tab[63] = 1.0; | |
188 for (i=1 ; i<64 ; i++){ | |
3106
9cbd63cca826
Don't use pow/powf functions where we just need integer arithmetic.
al
parents:
3091
diff
changeset
|
189 q->pow2tab[63+i]=(float)((uint64_t)1<<i); |
9cbd63cca826
Don't use pow/powf functions where we just need integer arithmetic.
al
parents:
3091
diff
changeset
|
190 q->pow2tab[63-i]=1.0/(float)((uint64_t)1<<i); |
2956 | 191 } |
192 } | |
193 | |
194 /* table generator */ | |
195 static void init_rootpow2table(COOKContext *q){ | |
196 int i; | |
197 q->rootpow2tab[63] = 1.0; | |
198 for (i=1 ; i<64 ; i++){ | |
3106
9cbd63cca826
Don't use pow/powf functions where we just need integer arithmetic.
al
parents:
3091
diff
changeset
|
199 q->rootpow2tab[63+i]=sqrt((float)((uint64_t)1<<i)); |
9cbd63cca826
Don't use pow/powf functions where we just need integer arithmetic.
al
parents:
3091
diff
changeset
|
200 q->rootpow2tab[63-i]=sqrt(1.0/(float)((uint64_t)1<<i)); |
2956 | 201 } |
202 } | |
203 | |
204 /* table generator */ | |
205 static void init_gain_table(COOKContext *q) { | |
206 int i; | |
207 q->gain_size_factor = q->samples_per_channel/8; | |
208 for (i=0 ; i<23 ; i++) { | |
209 q->gain_table[i] = pow((double)q->pow2tab[i+52] , | |
210 (1.0/(double)q->gain_size_factor)); | |
211 } | |
212 } | |
213 | |
214 | |
215 static int init_cook_vlc_tables(COOKContext *q) { | |
216 int i, result; | |
217 | |
218 result = 0; | |
219 for (i=0 ; i<13 ; i++) { | |
220 result &= init_vlc (&q->envelope_quant_index[i], 9, 24, | |
221 envelope_quant_index_huffbits[i], 1, 1, | |
222 envelope_quant_index_huffcodes[i], 2, 2, 0); | |
223 } | |
224 av_log(NULL,AV_LOG_DEBUG,"sqvh VLC init\n"); | |
225 for (i=0 ; i<7 ; i++) { | |
226 result &= init_vlc (&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i], | |
227 cvh_huffbits[i], 1, 1, | |
228 cvh_huffcodes[i], 2, 2, 0); | |
229 } | |
230 | |
231 if (q->nb_channels==2 && q->joint_stereo==1){ | |
232 result &= init_vlc (&q->ccpl, 6, (1<<q->js_vlc_bits)-1, | |
233 ccpl_huffbits[q->js_vlc_bits-2], 1, 1, | |
234 ccpl_huffcodes[q->js_vlc_bits-2], 2, 2, 0); | |
235 av_log(NULL,AV_LOG_DEBUG,"Joint-stereo VLC used.\n"); | |
236 } | |
237 | |
238 av_log(NULL,AV_LOG_DEBUG,"VLC tables initialized.\n"); | |
239 return result; | |
240 } | |
241 | |
242 static int init_cook_mlt(COOKContext *q) { | |
243 int j; | |
244 float alpha; | |
245 | |
246 /* Allocate the buffers, could be replaced with a static [512] | |
247 array if needed. */ | |
248 q->mlt_size = q->samples_per_channel; | |
249 q->mlt_window = av_malloc(sizeof(float)*q->mlt_size); | |
250 q->mlt_precos = av_malloc(sizeof(float)*q->mlt_size/2); | |
251 q->mlt_presin = av_malloc(sizeof(float)*q->mlt_size/2); | |
252 q->mlt_postcos = av_malloc(sizeof(float)*q->mlt_size/2); | |
253 | |
254 /* Initialize the MLT window: simple sine window. */ | |
255 alpha = M_PI / (2.0 * (float)q->mlt_size); | |
256 for(j=0 ; j<q->mlt_size ; j++) { | |
257 q->mlt_window[j] = sin((j + 512.0/(float)q->mlt_size) * alpha); | |
258 } | |
259 | |
260 /* pre/post twiddle factors */ | |
261 for (j=0 ; j<q->mlt_size/2 ; j++){ | |
262 q->mlt_precos[j] = cos( ((j+0.25)*M_PI)/q->mlt_size); | |
263 q->mlt_presin[j] = sin( ((j+0.25)*M_PI)/q->mlt_size); | |
264 q->mlt_postcos[j] = (float)sqrt(2.0/(float)q->mlt_size)*cos( ((float)j*M_PI) /q->mlt_size); //sqrt(2/MLT_size) = scalefactor | |
265 } | |
266 | |
267 /* Initialize the FFT. */ | |
268 ff_fft_init(&q->fft_ctx, av_log2(q->mlt_size)-1, 0); | |
269 av_log(NULL,AV_LOG_DEBUG,"FFT initialized, order = %d.\n", | |
270 av_log2(q->samples_per_channel)-1); | |
271 | |
272 return (int)(q->mlt_window && q->mlt_precos && q->mlt_presin && q->mlt_postcos); | |
273 } | |
274 | |
275 /*************** init functions end ***********/ | |
276 | |
277 /** | |
278 * Cook indata decoding, every 32 bits are XORed with 0x37c511f2. | |
279 * Why? No idea, some checksum/error detection method maybe. | |
280 * Nice way to waste CPU cycles. | |
281 * | |
282 * @param in pointer to 32bit array of indata | |
283 * @param bits amount of bits | |
284 * @param out pointer to 32bit array of outdata | |
285 */ | |
286 | |
287 static inline void decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){ | |
288 int i; | |
289 uint32_t* buf = (uint32_t*) inbuffer; | |
290 uint32_t* obuf = (uint32_t*) out; | |
291 /* FIXME: 64 bit platforms would be able to do 64 bits at a time. | |
292 * I'm too lazy though, should be something like | |
293 * for(i=0 ; i<bitamount/64 ; i++) | |
294 * (int64_t)out[i] = 0x37c511f237c511f2^be2me_64(int64_t)in[i]); | |
295 * Buffer alignment needs to be checked. */ | |
296 | |
297 | |
298 for(i=0 ; i<bytes/4 ; i++){ | |
299 #ifdef WORDS_BIGENDIAN | |
300 obuf[i] = 0x37c511f2^buf[i]; | |
301 #else | |
302 obuf[i] = 0xf211c537^buf[i]; | |
303 #endif | |
304 } | |
305 } | |
306 | |
307 /** | |
308 * Cook uninit | |
309 */ | |
310 | |
311 static int cook_decode_close(AVCodecContext *avctx) | |
312 { | |
313 int i; | |
314 COOKContext *q = avctx->priv_data; | |
315 av_log(NULL,AV_LOG_DEBUG, "Deallocating memory.\n"); | |
316 | |
317 /* Free allocated memory buffers. */ | |
318 av_free(q->mlt_window); | |
319 av_free(q->mlt_precos); | |
320 av_free(q->mlt_presin); | |
321 av_free(q->mlt_postcos); | |
322 av_free(q->decoded_bytes_buffer); | |
323 | |
324 /* Free the transform. */ | |
325 ff_fft_end(&q->fft_ctx); | |
326 | |
327 /* Free the VLC tables. */ | |
328 for (i=0 ; i<13 ; i++) { | |
329 free_vlc(&q->envelope_quant_index[i]); | |
330 } | |
331 for (i=0 ; i<7 ; i++) { | |
332 free_vlc(&q->sqvh[i]); | |
333 } | |
334 if(q->nb_channels==2 && q->joint_stereo==1 ){ | |
335 free_vlc(&q->ccpl); | |
336 } | |
337 | |
338 av_log(NULL,AV_LOG_DEBUG,"Memory deallocated.\n"); | |
339 | |
340 return 0; | |
341 } | |
342 | |
343 /** | |
344 * Fill the COOKgain structure for the timedomain quantization. | |
345 * | |
346 * @param q pointer to the COOKContext | |
347 * @param gaininfo pointer to the COOKgain | |
348 */ | |
349 | |
350 static void decode_gain_info(GetBitContext *gb, COOKgain* gaininfo) { | |
351 int i; | |
352 | |
353 while (get_bits1(gb)) {} | |
354 | |
355 gaininfo->size = get_bits_count(gb) - 1; //amount of elements*2 to update | |
356 | |
357 if (get_bits_count(gb) - 1 <= 0) return; | |
358 | |
359 for (i=0 ; i<gaininfo->size ; i++){ | |
360 gaininfo->qidx_table1[i] = get_bits(gb,3); | |
361 if (get_bits1(gb)) { | |
362 gaininfo->qidx_table2[i] = get_bits(gb,4) - 7; //convert to signed | |
363 } else { | |
364 gaininfo->qidx_table2[i] = -1; | |
365 } | |
366 } | |
367 } | |
368 | |
369 /** | |
370 * Create the quant index table needed for the envelope. | |
371 * | |
372 * @param q pointer to the COOKContext | |
373 * @param quant_index_table pointer to the array | |
374 */ | |
375 | |
376 static void decode_envelope(COOKContext *q, int* quant_index_table) { | |
377 int i,j, vlc_index; | |
378 int bitbias; | |
379 | |
380 bitbias = get_bits_count(&q->gb); | |
381 quant_index_table[0]= get_bits(&q->gb,6) - 6; //This is used later in categorize | |
382 | |
383 for (i=1 ; i < q->total_subbands ; i++){ | |
384 vlc_index=i; | |
385 if (i >= q->js_subband_start * 2) { | |
386 vlc_index-=q->js_subband_start; | |
387 } else { | |
388 vlc_index/=2; | |
389 if(vlc_index < 1) vlc_index = 1; | |
390 } | |
391 if (vlc_index>13) vlc_index = 13; //the VLC tables >13 are identical to No. 13 | |
392 | |
393 j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index-1].table, | |
394 q->envelope_quant_index[vlc_index-1].bits,2); | |
395 quant_index_table[i] = quant_index_table[i-1] + j - 12; //differential encoding | |
396 } | |
397 } | |
398 | |
399 /** | |
400 * Create the quant value table. | |
401 * | |
402 * @param q pointer to the COOKContext | |
403 * @param quant_value_table pointer to the array | |
404 */ | |
405 | |
406 static void inline dequant_envelope(COOKContext *q, int* quant_index_table, | |
407 float* quant_value_table){ | |
408 | |
409 int i; | |
410 for(i=0 ; i < q->total_subbands ; i++){ | |
411 quant_value_table[i] = q->rootpow2tab[quant_index_table[i]+63]; | |
412 } | |
413 } | |
414 | |
415 /** | |
416 * Calculate the category and category_index vector. | |
417 * | |
418 * @param q pointer to the COOKContext | |
419 * @param quant_index_table pointer to the array | |
420 * @param category pointer to the category array | |
421 * @param category_index pointer to the category_index array | |
422 */ | |
423 | |
424 static void categorize(COOKContext *q, int* quant_index_table, | |
425 int* category, int* category_index){ | |
426 int exp_idx, bias, tmpbias, bits_left, num_bits, index, v, i, j; | |
427 int exp_index2[102]; | |
428 int exp_index1[102]; | |
429 | |
430 int tmp_categorize_array1[128]; | |
431 int tmp_categorize_array1_idx=0; | |
432 int tmp_categorize_array2[128]; | |
433 int tmp_categorize_array2_idx=0; | |
434 int category_index_size=0; | |
435 | |
436 bits_left = q->bits_per_subpacket - get_bits_count(&q->gb); | |
437 | |
438 if(bits_left > q->samples_per_channel) { | |
439 bits_left = q->samples_per_channel + | |
440 ((bits_left - q->samples_per_channel)*5)/8; | |
441 //av_log(NULL, AV_LOG_ERROR, "bits_left = %d\n",bits_left); | |
442 } | |
443 | |
444 memset(&exp_index1,0,102*sizeof(int)); | |
445 memset(&exp_index2,0,102*sizeof(int)); | |
446 memset(&tmp_categorize_array1,0,128*sizeof(int)); | |
447 memset(&tmp_categorize_array2,0,128*sizeof(int)); | |
448 | |
449 bias=-32; | |
450 | |
451 /* Estimate bias. */ | |
452 for (i=32 ; i>0 ; i=i/2){ | |
453 num_bits = 0; | |
454 index = 0; | |
455 for (j=q->total_subbands ; j>0 ; j--){ | |
456 exp_idx = (i - quant_index_table[index] + bias) / 2; | |
457 if (exp_idx<0){ | |
458 exp_idx=0; | |
459 } else if(exp_idx >7) { | |
460 exp_idx=7; | |
461 } | |
462 index++; | |
463 num_bits+=expbits_tab[exp_idx]; | |
464 } | |
465 if(num_bits >= bits_left - 32){ | |
466 bias+=i; | |
467 } | |
468 } | |
469 | |
470 /* Calculate total number of bits. */ | |
471 num_bits=0; | |
472 for (i=0 ; i<q->total_subbands ; i++) { | |
473 exp_idx = (bias - quant_index_table[i]) / 2; | |
474 if (exp_idx<0) { | |
475 exp_idx=0; | |
476 } else if(exp_idx >7) { | |
477 exp_idx=7; | |
478 } | |
479 num_bits += expbits_tab[exp_idx]; | |
480 exp_index1[i] = exp_idx; | |
481 exp_index2[i] = exp_idx; | |
482 } | |
483 tmpbias = bias = num_bits; | |
484 | |
485 for (j = 1 ; j < q->numvector_size ; j++) { | |
486 if (tmpbias + bias > 2*bits_left) { /* ---> */ | |
487 int max = -999999; | |
488 index=-1; | |
489 for (i=0 ; i<q->total_subbands ; i++){ | |
490 if (exp_index1[i] < 7) { | |
491 v = (-2*exp_index1[i]) - quant_index_table[i] - 32; | |
492 if ( v >= max) { | |
493 max = v; | |
494 index = i; | |
495 } | |
496 } | |
497 } | |
498 if(index==-1)break; | |
499 tmp_categorize_array1[tmp_categorize_array1_idx++] = index; | |
500 tmpbias -= expbits_tab[exp_index1[index]] - | |
501 expbits_tab[exp_index1[index]+1]; | |
502 ++exp_index1[index]; | |
503 } else { /* <--- */ | |
504 int min = 999999; | |
505 index=-1; | |
506 for (i=0 ; i<q->total_subbands ; i++){ | |
507 if(exp_index2[i] > 0){ | |
508 v = (-2*exp_index2[i])-quant_index_table[i]; | |
509 if ( v < min) { | |
510 min = v; | |
511 index = i; | |
512 } | |
513 } | |
514 } | |
515 if(index == -1)break; | |
516 tmp_categorize_array2[tmp_categorize_array2_idx++] = index; | |
517 tmpbias -= expbits_tab[exp_index2[index]] - | |
518 expbits_tab[exp_index2[index]-1]; | |
519 --exp_index2[index]; | |
520 } | |
521 } | |
522 | |
523 for(i=0 ; i<q->total_subbands ; i++) | |
524 category[i] = exp_index2[i]; | |
525 | |
526 /* Concatenate the two arrays. */ | |
527 for(i=tmp_categorize_array2_idx-1 ; i >= 0; i--) | |
528 category_index[category_index_size++] = tmp_categorize_array2[i]; | |
529 | |
530 for(i=0;i<tmp_categorize_array1_idx;i++) | |
531 category_index[category_index_size++ ] = tmp_categorize_array1[i]; | |
532 | |
533 /* FIXME: mc_sich_ra8_20.rm triggers this, not sure with what we | |
534 should fill the remaining bytes. */ | |
535 for(i=category_index_size;i<q->numvector_size;i++) | |
536 category_index[i]=0; | |
537 | |
538 } | |
539 | |
540 | |
541 /** | |
542 * Expand the category vector. | |
543 * | |
544 * @param q pointer to the COOKContext | |
545 * @param category pointer to the category array | |
546 * @param category_index pointer to the category_index array | |
547 */ | |
548 | |
549 static void inline expand_category(COOKContext *q, int* category, | |
550 int* category_index){ | |
551 int i; | |
552 for(i=0 ; i<q->num_vectors ; i++){ | |
553 ++category[category_index[i]]; | |
554 } | |
555 } | |
556 | |
557 /** | |
558 * The real requantization of the mltcoefs | |
559 * | |
560 * @param q pointer to the COOKContext | |
561 * @param index index | |
562 * @param band current subband | |
563 * @param quant_value_table pointer to the array | |
564 * @param subband_coef_index array of indexes to quant_centroid_tab | |
565 * @param subband_coef_noise use random noise instead of predetermined value | |
566 * @param mlt_buffer pointer to the mlt buffer | |
567 */ | |
568 | |
569 | |
570 static void scalar_dequant(COOKContext *q, int index, int band, | |
571 float* quant_value_table, int* subband_coef_index, | |
572 int* subband_coef_noise, float* mlt_buffer){ | |
573 int i; | |
574 float f1; | |
575 | |
576 for(i=0 ; i<SUBBAND_SIZE ; i++) { | |
577 if (subband_coef_index[i]) { | |
578 if (subband_coef_noise[i]) { | |
579 f1 = -quant_centroid_tab[index][subband_coef_index[i]]; | |
580 } else { | |
581 f1 = quant_centroid_tab[index][subband_coef_index[i]]; | |
582 } | |
583 } else { | |
584 /* noise coding if subband_coef_noise[i] == 0 */ | |
585 q->random_state = q->random_state * 214013 + 2531011; //typical RNG numbers | |
586 f1 = randsign[(q->random_state/0x1000000)&1] * dither_tab[index]; //>>31 | |
587 } | |
588 mlt_buffer[band*20+ i] = f1 * quant_value_table[band]; | |
589 } | |
590 } | |
591 /** | |
592 * Unpack the subband_coef_index and subband_coef_noise vectors. | |
593 * | |
594 * @param q pointer to the COOKContext | |
595 * @param category pointer to the category array | |
596 * @param subband_coef_index array of indexes to quant_centroid_tab | |
597 * @param subband_coef_noise use random noise instead of predetermined value | |
598 */ | |
599 | |
600 static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index, | |
601 int* subband_coef_noise) { | |
602 int i,j; | |
603 int vlc, vd ,tmp, result; | |
604 int ub; | |
605 int cb; | |
606 | |
607 vd = vd_tab[category]; | |
608 result = 0; | |
609 for(i=0 ; i<vpr_tab[category] ; i++){ | |
610 ub = get_bits_count(&q->gb); | |
611 vlc = get_vlc2(&q->gb, q->sqvh[category].table, q->sqvh[category].bits, 3); | |
612 cb = get_bits_count(&q->gb); | |
613 if (q->bits_per_subpacket < get_bits_count(&q->gb)){ | |
614 vlc = 0; | |
615 result = 1; | |
616 } | |
617 for(j=vd-1 ; j>=0 ; j--){ | |
618 tmp = (vlc * invradix_tab[category])/0x100000; | |
619 subband_coef_index[vd*i+j] = vlc - tmp * (kmax_tab[category]+1); | |
620 vlc = tmp; | |
621 } | |
622 for(j=0 ; j<vd ; j++){ | |
623 if (subband_coef_index[i*vd + j]) { | |
624 if(get_bits_count(&q->gb) < q->bits_per_subpacket){ | |
625 subband_coef_noise[i*vd+j] = get_bits1(&q->gb); | |
626 } else { | |
627 result=1; | |
628 subband_coef_noise[i*vd+j]=0; | |
629 } | |
630 } else { | |
631 subband_coef_noise[i*vd+j]=0; | |
632 } | |
633 } | |
634 } | |
635 return result; | |
636 } | |
637 | |
638 | |
639 /** | |
640 * Fill the mlt_buffer with mlt coefficients. | |
641 * | |
642 * @param q pointer to the COOKContext | |
643 * @param category pointer to the category array | |
644 * @param quant_value_table pointer to the array | |
645 * @param mlt_buffer pointer to mlt coefficients | |
646 */ | |
647 | |
648 | |
649 static void decode_vectors(COOKContext* q, int* category, | |
650 float* quant_value_table, float* mlt_buffer){ | |
651 /* A zero in this table means that the subband coefficient is | |
652 random noise coded. */ | |
653 int subband_coef_noise[SUBBAND_SIZE]; | |
654 /* A zero in this table means that the subband coefficient is a | |
655 positive multiplicator. */ | |
656 int subband_coef_index[SUBBAND_SIZE]; | |
657 int band, j; | |
658 int index=0; | |
659 | |
660 for(band=0 ; band<q->total_subbands ; band++){ | |
661 index = category[band]; | |
662 if(category[band] < 7){ | |
663 if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_noise)){ | |
664 index=7; | |
665 for(j=0 ; j<q->total_subbands ; j++) category[band+j]=7; | |
666 } | |
667 } | |
668 if(index==7) { | |
669 memset(subband_coef_index, 0, sizeof(subband_coef_index)); | |
670 memset(subband_coef_noise, 0, sizeof(subband_coef_noise)); | |
671 } | |
672 scalar_dequant(q, index, band, quant_value_table, subband_coef_index, | |
673 subband_coef_noise, mlt_buffer); | |
674 } | |
675 | |
676 if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){ | |
677 return; | |
678 } | |
679 } | |
680 | |
681 | |
682 /** | |
683 * function for decoding mono data | |
684 * | |
685 * @param q pointer to the COOKContext | |
686 * @param mlt_buffer1 pointer to left channel mlt coefficients | |
687 * @param mlt_buffer2 pointer to right channel mlt coefficients | |
688 */ | |
689 | |
690 static void mono_decode(COOKContext *q, float* mlt_buffer) { | |
691 | |
692 int category_index[128]; | |
693 float quant_value_table[102]; | |
694 int quant_index_table[102]; | |
695 int category[128]; | |
696 | |
697 memset(&category, 0, 128*sizeof(int)); | |
698 memset(&quant_value_table, 0, 102*sizeof(int)); | |
699 memset(&category_index, 0, 128*sizeof(int)); | |
700 | |
701 decode_envelope(q, quant_index_table); | |
3090 | 702 q->num_vectors = get_bits(&q->gb,q->log2_numvector_size); |
2956 | 703 dequant_envelope(q, quant_index_table, quant_value_table); |
704 categorize(q, quant_index_table, category, category_index); | |
705 expand_category(q, category, category_index); | |
706 decode_vectors(q, category, quant_value_table, mlt_buffer); | |
707 } | |
708 | |
709 | |
710 /** | |
711 * The modulated lapped transform, this takes transform coefficients | |
712 * and transforms them into timedomain samples. This is done through | |
713 * an FFT-based algorithm with pre- and postrotation steps. | |
714 * A window and reorder step is also included. | |
715 * | |
716 * @param q pointer to the COOKContext | |
717 * @param inbuffer pointer to the mltcoefficients | |
718 * @param outbuffer pointer to the timedomain buffer | |
719 * @param mlt_tmp pointer to temporary storage space | |
720 */ | |
721 | |
722 static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer, | |
723 float* mlt_tmp){ | |
724 int i; | |
725 | |
726 /* prerotation */ | |
727 for(i=0 ; i<q->mlt_size ; i+=2){ | |
728 outbuffer[i] = (q->mlt_presin[i/2] * inbuffer[q->mlt_size-1-i]) + | |
729 (q->mlt_precos[i/2] * inbuffer[i]); | |
730 outbuffer[i+1] = (q->mlt_precos[i/2] * inbuffer[q->mlt_size-1-i]) - | |
731 (q->mlt_presin[i/2] * inbuffer[i]); | |
732 } | |
733 | |
734 /* FFT */ | |
735 ff_fft_permute(&q->fft_ctx, (FFTComplex *) outbuffer); | |
736 ff_fft_calc (&q->fft_ctx, (FFTComplex *) outbuffer); | |
737 | |
738 /* postrotation */ | |
739 for(i=0 ; i<q->mlt_size ; i+=2){ | |
740 mlt_tmp[i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i+1]) + | |
741 (q->mlt_postcos[i/2] * outbuffer[i]); | |
742 mlt_tmp[q->mlt_size-1-i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i]) - | |
743 (q->mlt_postcos[i/2] * outbuffer[i+1]); | |
744 } | |
745 | |
746 /* window and reorder */ | |
747 for(i=0 ; i<q->mlt_size/2 ; i++){ | |
748 outbuffer[i] = mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[i]; | |
749 outbuffer[q->mlt_size-1-i]= mlt_tmp[q->mlt_size/2-1-i] * | |
750 q->mlt_window[q->mlt_size-1-i]; | |
751 outbuffer[q->mlt_size+i]= mlt_tmp[q->mlt_size/2+i] * | |
752 q->mlt_window[q->mlt_size-1-i]; | |
753 outbuffer[2*q->mlt_size-1-i]= -(mlt_tmp[q->mlt_size/2+i] * | |
754 q->mlt_window[i]); | |
755 } | |
756 } | |
757 | |
758 | |
759 /** | |
760 * the actual requantization of the timedomain samples | |
761 * | |
762 * @param q pointer to the COOKContext | |
763 * @param buffer pointer to the timedomain buffer | |
764 * @param gain_index index for the block multiplier | |
765 * @param gain_index_next index for the next block multiplier | |
766 */ | |
767 | |
768 static void interpolate(COOKContext *q, float* buffer, | |
769 int gain_index, int gain_index_next){ | |
770 int i; | |
771 float fc1, fc2; | |
772 fc1 = q->pow2tab[gain_index+63]; | |
773 | |
774 if(gain_index == gain_index_next){ //static gain | |
775 for(i=0 ; i<q->gain_size_factor ; i++){ | |
776 buffer[i]*=fc1; | |
777 } | |
778 return; | |
779 } else { //smooth gain | |
780 fc2 = q->gain_table[11 + (gain_index_next-gain_index)]; | |
781 for(i=0 ; i<q->gain_size_factor ; i++){ | |
782 buffer[i]*=fc1; | |
783 fc1*=fc2; | |
784 } | |
785 return; | |
786 } | |
787 } | |
788 | |
789 /** | |
790 * timedomain requantization of the timedomain samples | |
791 * | |
792 * @param q pointer to the COOKContext | |
793 * @param buffer pointer to the timedomain buffer | |
794 * @param gain_now current gain structure | |
795 * @param gain_previous previous gain structure | |
796 */ | |
797 | |
798 static void gain_window(COOKContext *q, float* buffer, COOKgain* gain_now, | |
799 COOKgain* gain_previous){ | |
800 int i, index; | |
801 int gain_index[9]; | |
802 int tmp_gain_index; | |
803 | |
804 gain_index[8]=0; | |
805 index = gain_previous->size; | |
806 for (i=7 ; i>=0 ; i--) { | |
807 if(index && gain_previous->qidx_table1[index-1]==i) { | |
808 gain_index[i] = gain_previous->qidx_table2[index-1]; | |
809 index--; | |
810 } else { | |
811 gain_index[i]=gain_index[i+1]; | |
812 } | |
813 } | |
814 /* This is applied to the to be previous data buffer. */ | |
815 for(i=0;i<8;i++){ | |
816 interpolate(q, &buffer[q->samples_per_channel+q->gain_size_factor*i], | |
817 gain_index[i], gain_index[i+1]); | |
818 } | |
819 | |
820 tmp_gain_index = gain_index[0]; | |
821 index = gain_now->size; | |
822 for (i=7 ; i>=0 ; i--) { | |
823 if(index && gain_now->qidx_table1[index-1]==i) { | |
824 gain_index[i]= gain_now->qidx_table2[index-1]; | |
825 index--; | |
826 } else { | |
827 gain_index[i]=gain_index[i+1]; | |
828 } | |
829 } | |
830 | |
831 /* This is applied to the to be current block. */ | |
832 for(i=0;i<8;i++){ | |
833 interpolate(q, &buffer[i*q->gain_size_factor], | |
834 tmp_gain_index+gain_index[i], | |
835 tmp_gain_index+gain_index[i+1]); | |
836 } | |
837 } | |
838 | |
839 | |
840 /** | |
841 * mlt overlapping and buffer management | |
842 * | |
843 * @param q pointer to the COOKContext | |
844 * @param buffer pointer to the timedomain buffer | |
845 * @param gain_now current gain structure | |
846 * @param gain_previous previous gain structure | |
847 * @param previous_buffer pointer to the previous buffer to be used for overlapping | |
848 * | |
849 */ | |
850 | |
851 static void gain_compensate(COOKContext *q, float* buffer, COOKgain* gain_now, | |
852 COOKgain* gain_previous, float* previous_buffer) { | |
853 int i; | |
854 if((gain_now->size || gain_previous->size)) { | |
855 gain_window(q, buffer, gain_now, gain_previous); | |
856 } | |
857 | |
858 /* Overlap with the previous block. */ | |
859 for(i=0 ; i<q->samples_per_channel ; i++) buffer[i]+=previous_buffer[i]; | |
860 | |
861 /* Save away the current to be previous block. */ | |
862 memcpy(previous_buffer, buffer+q->samples_per_channel, | |
863 sizeof(float)*q->samples_per_channel); | |
864 } | |
865 | |
866 | |
867 /** | |
868 * function for getting the jointstereo coupling information | |
869 * | |
870 * @param q pointer to the COOKContext | |
871 * @param decouple_tab decoupling array | |
872 * | |
873 */ | |
874 | |
875 static void decouple_info(COOKContext *q, int* decouple_tab){ | |
876 int length, i; | |
877 | |
878 if(get_bits1(&q->gb)) { | |
879 if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return; | |
880 | |
881 length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1; | |
882 for (i=0 ; i<length ; i++) { | |
883 decouple_tab[cplband[q->js_subband_start] + i] = get_vlc2(&q->gb, q->ccpl.table, q->ccpl.bits, 2); | |
884 } | |
885 return; | |
886 } | |
887 | |
888 if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return; | |
889 | |
890 length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1; | |
891 for (i=0 ; i<length ; i++) { | |
892 decouple_tab[cplband[q->js_subband_start] + i] = get_bits(&q->gb, q->js_vlc_bits); | |
893 } | |
894 return; | |
895 } | |
896 | |
897 | |
898 /** | |
899 * function for decoding joint stereo data | |
900 * | |
901 * @param q pointer to the COOKContext | |
902 * @param mlt_buffer1 pointer to left channel mlt coefficients | |
903 * @param mlt_buffer2 pointer to right channel mlt coefficients | |
904 */ | |
905 | |
906 static void joint_decode(COOKContext *q, float* mlt_buffer1, | |
907 float* mlt_buffer2) { | |
908 int i,j; | |
909 int decouple_tab[SUBBAND_SIZE]; | |
3009
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
910 float decode_buffer[1060]; |
2956 | 911 int idx, cpl_tmp,tmp_idx; |
912 float f1,f2; | |
913 float* cplscale; | |
914 | |
915 memset(decouple_tab, 0, sizeof(decouple_tab)); | |
916 memset(decode_buffer, 0, sizeof(decode_buffer)); | |
917 | |
918 /* Make sure the buffers are zeroed out. */ | |
919 memset(mlt_buffer1,0, 1024*sizeof(float)); | |
920 memset(mlt_buffer2,0, 1024*sizeof(float)); | |
921 decouple_info(q, decouple_tab); | |
922 mono_decode(q, decode_buffer); | |
923 | |
924 /* The two channels are stored interleaved in decode_buffer. */ | |
925 for (i=0 ; i<q->js_subband_start ; i++) { | |
926 for (j=0 ; j<SUBBAND_SIZE ; j++) { | |
927 mlt_buffer1[i*20+j] = decode_buffer[i*40+j]; | |
928 mlt_buffer2[i*20+j] = decode_buffer[i*40+20+j]; | |
929 } | |
930 } | |
931 | |
932 /* When we reach js_subband_start (the higher frequencies) | |
933 the coefficients are stored in a coupling scheme. */ | |
934 idx = (1 << q->js_vlc_bits) - 1; | |
3009
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
935 for (i=q->js_subband_start ; i<q->subbands ; i++) { |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
936 cpl_tmp = cplband[i]; |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
937 idx -=decouple_tab[cpl_tmp]; |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
938 cplscale = (float*)cplscales[q->js_vlc_bits-2]; //choose decoupler table |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
939 f1 = cplscale[decouple_tab[cpl_tmp]]; |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
940 f2 = cplscale[idx-1]; |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
941 for (j=0 ; j<SUBBAND_SIZE ; j++) { |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
942 tmp_idx = ((q->js_subband_start + i)*20)+j; |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
943 mlt_buffer1[20*i + j] = f1 * decode_buffer[tmp_idx]; |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
944 mlt_buffer2[20*i + j] = f2 * decode_buffer[tmp_idx]; |
2956 | 945 } |
3009
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
946 idx = (1 << q->js_vlc_bits) - 1; |
2956 | 947 } |
948 } | |
949 | |
950 /** | |
951 * Cook subpacket decoding. This function returns one decoded subpacket, | |
952 * usually 1024 samples per channel. | |
953 * | |
954 * @param q pointer to the COOKContext | |
955 * @param inbuffer pointer to the inbuffer | |
956 * @param sub_packet_size subpacket size | |
957 * @param outbuffer pointer to the outbuffer | |
958 */ | |
959 | |
960 | |
961 static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, | |
962 int sub_packet_size, int16_t *outbuffer) { | |
963 int i,j; | |
964 int value; | |
965 float* tmp_ptr; | |
966 | |
967 /* packet dump */ | |
968 // for (i=0 ; i<sub_packet_size ; i++) { | |
969 // av_log(NULL, AV_LOG_ERROR, "%02x", inbuffer[i]); | |
970 // } | |
971 // av_log(NULL, AV_LOG_ERROR, "\n"); | |
972 | |
973 decode_bytes(inbuffer, q->decoded_bytes_buffer, sub_packet_size); | |
974 init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8); | |
975 decode_gain_info(&q->gb, &q->gain_current); | |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
976 |
2956 | 977 if(q->nb_channels==2 && q->joint_stereo==1){ |
978 joint_decode(q, q->decode_buf_ptr[0], q->decode_buf_ptr[2]); | |
979 | |
980 /* Swap buffer pointers. */ | |
981 tmp_ptr = q->decode_buf_ptr[1]; | |
982 q->decode_buf_ptr[1] = q->decode_buf_ptr[0]; | |
983 q->decode_buf_ptr[0] = tmp_ptr; | |
984 tmp_ptr = q->decode_buf_ptr[3]; | |
985 q->decode_buf_ptr[3] = q->decode_buf_ptr[2]; | |
986 q->decode_buf_ptr[2] = tmp_ptr; | |
987 | |
988 /* FIXME: Rethink the gainbuffer handling, maybe a rename? | |
989 now/previous swap */ | |
990 q->gain_now_ptr = &q->gain_now; | |
991 q->gain_previous_ptr = &q->gain_previous; | |
992 for (i=0 ; i<q->nb_channels ; i++){ | |
993 | |
994 cook_imlt(q, q->decode_buf_ptr[i*2], q->mono_mdct_output, q->mlt_tmp); | |
995 gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr, | |
996 q->gain_previous_ptr, q->previous_buffer_ptr[0]); | |
997 | |
998 /* Swap out the previous buffer. */ | |
999 tmp_ptr = q->previous_buffer_ptr[0]; | |
1000 q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1]; | |
1001 q->previous_buffer_ptr[1] = tmp_ptr; | |
1002 | |
1003 /* Clip and convert the floats to 16 bits. */ | |
1004 for (j=0 ; j<q->samples_per_frame ; j++){ | |
1005 value = lrintf(q->mono_mdct_output[j]); | |
1006 if(value < -32768) value = -32768; | |
1007 else if(value > 32767) value = 32767; | |
1008 outbuffer[2*j+i] = value; | |
1009 } | |
1010 } | |
1011 | |
1012 memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain)); | |
1013 memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain)); | |
1014 | |
1015 } else if (q->nb_channels==2 && q->joint_stereo==0) { | |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1016 /* channel 0 */ |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1017 mono_decode(q, q->decode_buf_ptr2[0]); |
2956 | 1018 |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1019 tmp_ptr = q->decode_buf_ptr2[0]; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1020 q->decode_buf_ptr2[0] = q->decode_buf_ptr2[1]; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1021 q->decode_buf_ptr2[1] = tmp_ptr; |
2956 | 1022 |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1023 memcpy(&q->gain_channel1[0], &q->gain_current ,sizeof(COOKgain)); |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1024 q->gain_now_ptr = &q->gain_channel1[0]; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1025 q->gain_previous_ptr = &q->gain_channel1[1]; |
2956 | 1026 |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1027 cook_imlt(q, q->decode_buf_ptr2[0], q->mono_mdct_output,q->mlt_tmp); |
2956 | 1028 gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr, |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1029 q->gain_previous_ptr, q->mono_previous_buffer1); |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1030 |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1031 memcpy(&q->gain_channel1[1], &q->gain_channel1[0],sizeof(COOKgain)); |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1032 |
2956 | 1033 |
1034 for (j=0 ; j<q->samples_per_frame ; j++){ | |
1035 value = lrintf(q->mono_mdct_output[j]); | |
1036 if(value < -32768) value = -32768; | |
1037 else if(value > 32767) value = 32767; | |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1038 outbuffer[2*j+1] = value; |
2956 | 1039 } |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1040 |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1041 /* channel 1 */ |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1042 //av_log(NULL,AV_LOG_ERROR,"bits = %d\n",get_bits_count(&q->gb)); |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1043 init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8+q->bits_per_subpacket); |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1044 |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1045 q->gain_now_ptr = &q->gain_channel2[0]; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1046 q->gain_previous_ptr = &q->gain_channel2[1]; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1047 |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1048 decode_gain_info(&q->gb, &q->gain_channel2[0]); |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1049 mono_decode(q, q->decode_buf_ptr[0]); |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1050 |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1051 tmp_ptr = q->decode_buf_ptr[0]; |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1052 q->decode_buf_ptr[0] = q->decode_buf_ptr[1]; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1053 q->decode_buf_ptr[1] = tmp_ptr; |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1054 |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1055 cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp); |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1056 gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr, |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1057 q->gain_previous_ptr, q->mono_previous_buffer2); |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1058 |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1059 /* Swap out the previous buffer. */ |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1060 tmp_ptr = q->previous_buffer_ptr[0]; |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1061 q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1]; |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1062 q->previous_buffer_ptr[1] = tmp_ptr; |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1063 |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1064 memcpy(&q->gain_channel2[1], &q->gain_channel2[0] ,sizeof(COOKgain)); |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1065 |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1066 for (j=0 ; j<q->samples_per_frame ; j++){ |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1067 value = lrintf(q->mono_mdct_output[j]); |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1068 if(value < -32768) value = -32768; |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1069 else if(value > 32767) value = 32767; |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1070 outbuffer[2*j] = value; |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1071 } |
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1072 |
2956 | 1073 } else { |
1074 mono_decode(q, q->decode_buf_ptr[0]); | |
1075 | |
1076 /* Swap buffer pointers. */ | |
1077 tmp_ptr = q->decode_buf_ptr[1]; | |
1078 q->decode_buf_ptr[1] = q->decode_buf_ptr[0]; | |
1079 q->decode_buf_ptr[0] = tmp_ptr; | |
1080 | |
1081 /* FIXME: Rethink the gainbuffer handling, maybe a rename? | |
1082 now/previous swap */ | |
1083 q->gain_now_ptr = &q->gain_now; | |
1084 q->gain_previous_ptr = &q->gain_previous; | |
1085 | |
1086 cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp); | |
1087 gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr, | |
1088 q->gain_previous_ptr, q->mono_previous_buffer1); | |
1089 | |
1090 /* Clip and convert the floats to 16 bits */ | |
1091 for (j=0 ; j<q->samples_per_frame ; j++){ | |
1092 value = lrintf(q->mono_mdct_output[j]); | |
1093 if(value < -32768) value = -32768; | |
1094 else if(value > 32767) value = 32767; | |
1095 outbuffer[j] = value; | |
1096 } | |
1097 memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain)); | |
1098 memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain)); | |
1099 } | |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1100 return q->samples_per_frame * sizeof(int16_t); |
2956 | 1101 } |
1102 | |
1103 | |
1104 /** | |
1105 * Cook frame decoding | |
1106 * | |
1107 * @param avctx pointer to the AVCodecContext | |
1108 */ | |
1109 | |
1110 static int cook_decode_frame(AVCodecContext *avctx, | |
1111 void *data, int *data_size, | |
1112 uint8_t *buf, int buf_size) { | |
1113 COOKContext *q = avctx->priv_data; | |
1114 | |
1115 if (buf_size < avctx->block_align) | |
1116 return buf_size; | |
1117 | |
1118 *data_size = decode_subpacket(q, buf, avctx->block_align, data); | |
1119 | |
1120 return avctx->block_align; | |
1121 } | |
3090 | 1122 |
2956 | 1123 #ifdef COOKDEBUG |
1124 static void dump_cook_context(COOKContext *q, COOKextradata *e) | |
1125 { | |
1126 //int i=0; | |
1127 #define PRINT(a,b) av_log(NULL,AV_LOG_ERROR," %s = %d\n", a, b); | |
1128 av_log(NULL,AV_LOG_ERROR,"COOKextradata\n"); | |
1129 av_log(NULL,AV_LOG_ERROR,"cookversion=%x\n",e->cookversion); | |
1130 if (e->cookversion > MONO_COOK2) { | |
1131 PRINT("js_subband_start",e->js_subband_start); | |
1132 PRINT("js_vlc_bits",e->js_vlc_bits); | |
1133 } | |
1134 av_log(NULL,AV_LOG_ERROR,"COOKContext\n"); | |
1135 PRINT("nb_channels",q->nb_channels); | |
1136 PRINT("bit_rate",q->bit_rate); | |
1137 PRINT("sample_rate",q->sample_rate); | |
1138 PRINT("samples_per_channel",q->samples_per_channel); | |
1139 PRINT("samples_per_frame",q->samples_per_frame); | |
1140 PRINT("subbands",q->subbands); | |
1141 PRINT("random_state",q->random_state); | |
1142 PRINT("mlt_size",q->mlt_size); | |
1143 PRINT("js_subband_start",q->js_subband_start); | |
3090 | 1144 PRINT("log2_numvector_size",q->log2_numvector_size); |
2956 | 1145 PRINT("numvector_size",q->numvector_size); |
1146 PRINT("total_subbands",q->total_subbands); | |
1147 } | |
1148 #endif | |
3090 | 1149 |
2956 | 1150 /** |
1151 * Cook initialization | |
1152 * | |
1153 * @param avctx pointer to the AVCodecContext | |
1154 */ | |
1155 | |
1156 static int cook_decode_init(AVCodecContext *avctx) | |
1157 { | |
1158 COOKextradata *e = avctx->extradata; | |
1159 COOKContext *q = avctx->priv_data; | |
1160 | |
1161 /* Take care of the codec specific extradata. */ | |
1162 if (avctx->extradata_size <= 0) { | |
1163 av_log(NULL,AV_LOG_ERROR,"Necessary extradata missing!\n"); | |
1164 return -1; | |
1165 } else { | |
1166 /* 8 for mono, 16 for stereo, ? for multichannel | |
1167 Swap to right endianness so we don't need to care later on. */ | |
1168 av_log(NULL,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size); | |
1169 if (avctx->extradata_size >= 8){ | |
1170 e->cookversion = be2me_32(e->cookversion); | |
1171 e->samples_per_frame = be2me_16(e->samples_per_frame); | |
1172 e->subbands = be2me_16(e->subbands); | |
1173 } | |
1174 if (avctx->extradata_size >= 16){ | |
1175 e->js_subband_start = be2me_16(e->js_subband_start); | |
1176 e->js_vlc_bits = be2me_16(e->js_vlc_bits); | |
1177 } | |
1178 } | |
1179 | |
1180 /* Take data from the AVCodecContext (RM container). */ | |
1181 q->sample_rate = avctx->sample_rate; | |
1182 q->nb_channels = avctx->channels; | |
1183 q->bit_rate = avctx->bit_rate; | |
1184 | |
1185 /* Initialize state. */ | |
1186 q->random_state = 1; | |
1187 | |
1188 /* Initialize extradata related variables. */ | |
1189 q->samples_per_channel = e->samples_per_frame / q->nb_channels; | |
1190 q->samples_per_frame = e->samples_per_frame; | |
1191 q->subbands = e->subbands; | |
1192 q->bits_per_subpacket = avctx->block_align * 8; | |
1193 | |
1194 /* Initialize default data states. */ | |
1195 q->js_subband_start = 0; | |
3090 | 1196 q->log2_numvector_size = 5; |
2956 | 1197 q->total_subbands = q->subbands; |
1198 | |
1199 /* Initialize version-dependent variables */ | |
1200 av_log(NULL,AV_LOG_DEBUG,"e->cookversion=%x\n",e->cookversion); | |
1201 switch (e->cookversion) { | |
1202 case MONO_COOK1: | |
1203 if (q->nb_channels != 1) { | |
1204 av_log(NULL,AV_LOG_ERROR,"Container channels != 1, report sample!\n"); | |
1205 return -1; | |
1206 } | |
1207 av_log(NULL,AV_LOG_DEBUG,"MONO_COOK1\n"); | |
1208 break; | |
1209 case MONO_COOK2: | |
1210 if (q->nb_channels != 1) { | |
1211 q->joint_stereo = 0; | |
2959
24805f4d1b84
This patch adds some support for non-joint stereo streams. It also
rtognimp
parents:
2956
diff
changeset
|
1212 q->bits_per_subpacket = q->bits_per_subpacket/2; |
2956 | 1213 } |
1214 av_log(NULL,AV_LOG_DEBUG,"MONO_COOK2\n"); | |
1215 break; | |
1216 case JOINT_STEREO: | |
1217 if (q->nb_channels != 2) { | |
1218 av_log(NULL,AV_LOG_ERROR,"Container channels != 2, report sample!\n"); | |
1219 return -1; | |
1220 } | |
1221 av_log(NULL,AV_LOG_DEBUG,"JOINT_STEREO\n"); | |
1222 if (avctx->extradata_size >= 16){ | |
1223 q->total_subbands = q->subbands + e->js_subband_start; | |
1224 q->js_subband_start = e->js_subband_start; | |
1225 q->joint_stereo = 1; | |
1226 q->js_vlc_bits = e->js_vlc_bits; | |
1227 } | |
1228 if (q->samples_per_channel > 256) { | |
3091
0284d5b34916
Fix broken cosmetics commit and add a check for valid headers.
banan
parents:
3090
diff
changeset
|
1229 q->log2_numvector_size = 6; |
2956 | 1230 } |
1231 if (q->samples_per_channel > 512) { | |
3091
0284d5b34916
Fix broken cosmetics commit and add a check for valid headers.
banan
parents:
3090
diff
changeset
|
1232 q->log2_numvector_size = 7; |
2956 | 1233 } |
1234 break; | |
1235 case MC_COOK: | |
1236 av_log(NULL,AV_LOG_ERROR,"MC_COOK not supported!\n"); | |
1237 return -1; | |
1238 break; | |
1239 default: | |
1240 av_log(NULL,AV_LOG_ERROR,"Unknown Cook version, report sample!\n"); | |
1241 return -1; | |
1242 break; | |
1243 } | |
1244 | |
1245 /* Initialize variable relations */ | |
1246 q->mlt_size = q->samples_per_channel; | |
3090 | 1247 q->numvector_size = (1 << q->log2_numvector_size); |
2956 | 1248 |
1249 /* Generate tables */ | |
1250 init_rootpow2table(q); | |
1251 init_pow2table(q); | |
1252 init_gain_table(q); | |
1253 | |
1254 if (init_cook_vlc_tables(q) != 0) | |
1255 return -1; | |
1256 | |
3303
68721b62a528
sanity checks, some might have been exploitable ...
michael
parents:
3106
diff
changeset
|
1257 |
68721b62a528
sanity checks, some might have been exploitable ...
michael
parents:
3106
diff
changeset
|
1258 if(avctx->block_align >= UINT_MAX/2) |
68721b62a528
sanity checks, some might have been exploitable ...
michael
parents:
3106
diff
changeset
|
1259 return -1; |
68721b62a528
sanity checks, some might have been exploitable ...
michael
parents:
3106
diff
changeset
|
1260 |
2956 | 1261 /* Pad the databuffer with FF_INPUT_BUFFER_PADDING_SIZE, |
1262 this is for the bitstreamreader. */ | |
1263 if ((q->decoded_bytes_buffer = av_mallocz((avctx->block_align+(4-avctx->block_align%4) + FF_INPUT_BUFFER_PADDING_SIZE)*sizeof(uint8_t))) == NULL) | |
1264 return -1; | |
1265 | |
1266 q->decode_buf_ptr[0] = q->decode_buffer_1; | |
1267 q->decode_buf_ptr[1] = q->decode_buffer_2; | |
1268 q->decode_buf_ptr[2] = q->decode_buffer_3; | |
1269 q->decode_buf_ptr[3] = q->decode_buffer_4; | |
1270 | |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1271 q->decode_buf_ptr2[0] = q->decode_buffer_3; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1272 q->decode_buf_ptr2[1] = q->decode_buffer_4; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1273 |
2956 | 1274 q->previous_buffer_ptr[0] = q->mono_previous_buffer1; |
1275 q->previous_buffer_ptr[1] = q->mono_previous_buffer2; | |
1276 | |
1277 /* Initialize transform. */ | |
1278 if ( init_cook_mlt(q) == 0 ) | |
1279 return -1; | |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1280 |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1281 /* Try to catch some obviously faulty streams, othervise it might be exploitable */ |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1282 if (q->total_subbands > 53) { |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1283 av_log(NULL,AV_LOG_ERROR,"total_subbands > 53, report sample!\n"); |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1284 return -1; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1285 } |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1286 if (q->subbands > 50) { |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1287 av_log(NULL,AV_LOG_ERROR,"subbands > 50, report sample!\n"); |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1288 return -1; |
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1289 } |
3091
0284d5b34916
Fix broken cosmetics commit and add a check for valid headers.
banan
parents:
3090
diff
changeset
|
1290 if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) { |
0284d5b34916
Fix broken cosmetics commit and add a check for valid headers.
banan
parents:
3090
diff
changeset
|
1291 } else { |
0284d5b34916
Fix broken cosmetics commit and add a check for valid headers.
banan
parents:
3090
diff
changeset
|
1292 av_log(NULL,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel); |
0284d5b34916
Fix broken cosmetics commit and add a check for valid headers.
banan
parents:
3090
diff
changeset
|
1293 return -1; |
0284d5b34916
Fix broken cosmetics commit and add a check for valid headers.
banan
parents:
3090
diff
changeset
|
1294 } |
3014
959b8ad880dc
Dual mono stereo strems sound ok now, added sanity checks and removed
rtognimp
parents:
3009
diff
changeset
|
1295 |
3009
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
1296 #ifdef COOKDEBUG |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
1297 dump_cook_context(q,e); |
f5898b9b8a8a
Fix an out of array access and some minor cleanup of the code.
diego
parents:
2959
diff
changeset
|
1298 #endif |
2956 | 1299 return 0; |
1300 } | |
1301 | |
1302 | |
1303 AVCodec cook_decoder = | |
1304 { | |
1305 .name = "cook", | |
1306 .type = CODEC_TYPE_AUDIO, | |
1307 .id = CODEC_ID_COOK, | |
1308 .priv_data_size = sizeof(COOKContext), | |
1309 .init = cook_decode_init, | |
1310 .close = cook_decode_close, | |
1311 .decode = cook_decode_frame, | |
1312 }; |