Mercurial > libavcodec.hg
comparison cook.c @ 4650:31bf54d9353d libavcodec
Replace custom modified discrete cosine transform with ffmpeg's own.
This does alter the decoded output, but not by much.
The new output is closer to that produced by Real's "official" decoder,
and the decoder runs slightly faster.
Patch by Ian Braithwaite ian at braithwaite dot dk
author | banan |
---|---|
date | Sun, 11 Mar 2007 20:30:06 +0000 |
parents | 33fc84eae7c3 |
children | 1d88da25349b |
comparison
equal
deleted
inserted
replaced
4649:f64adef7cde8 | 4650:31bf54d9353d |
---|---|
88 int cookversion; | 88 int cookversion; |
89 /* states */ | 89 /* states */ |
90 int random_state; | 90 int random_state; |
91 | 91 |
92 /* transform data */ | 92 /* transform data */ |
93 FFTContext fft_ctx; | 93 MDCTContext mdct_ctx; |
94 DECLARE_ALIGNED_16(FFTSample, mlt_tmp[1024]); /* temporary storage for imlt */ | 94 DECLARE_ALIGNED_16(FFTSample, mdct_tmp[1024]); /* temporary storage for imlt */ |
95 float* mlt_window; | 95 float* mlt_window; |
96 float* mlt_precos; | |
97 float* mlt_presin; | |
98 float* mlt_postcos; | |
99 int fft_size; | |
100 int fft_order; | |
101 int mlt_size; //modulated lapped transform size | |
102 | 96 |
103 /* gain buffers */ | 97 /* gain buffers */ |
104 cook_gains gains1; | 98 cook_gains gains1; |
105 cook_gains gains2; | 99 cook_gains gains2; |
106 int gain_1[9]; | 100 int gain_1[9]; |
223 } | 217 } |
224 | 218 |
225 static int init_cook_mlt(COOKContext *q) { | 219 static int init_cook_mlt(COOKContext *q) { |
226 int j; | 220 int j; |
227 float alpha; | 221 float alpha; |
228 | 222 int mlt_size = q->samples_per_channel; |
229 /* Allocate the buffers, could be replaced with a static [512] | 223 |
230 array if needed. */ | 224 if ((q->mlt_window = av_malloc(sizeof(float)*mlt_size)) == 0) |
231 q->mlt_size = q->samples_per_channel; | 225 return -1; |
232 q->mlt_window = av_malloc(sizeof(float)*q->mlt_size); | |
233 q->mlt_precos = av_malloc(sizeof(float)*q->mlt_size/2); | |
234 q->mlt_presin = av_malloc(sizeof(float)*q->mlt_size/2); | |
235 q->mlt_postcos = av_malloc(sizeof(float)*q->mlt_size/2); | |
236 | 226 |
237 /* Initialize the MLT window: simple sine window. */ | 227 /* Initialize the MLT window: simple sine window. */ |
238 alpha = M_PI / (2.0 * (float)q->mlt_size); | 228 alpha = M_PI / (2.0 * (float)mlt_size); |
239 for(j=0 ; j<q->mlt_size ; j++) { | 229 for(j=0 ; j<mlt_size ; j++) |
240 q->mlt_window[j] = sin((j + 512.0/(float)q->mlt_size) * alpha); | 230 q->mlt_window[j] = sin((j + 0.5) * alpha) * sqrt(2.0 / q->samples_per_channel); |
241 } | 231 |
242 | 232 /* Initialize the MDCT. */ |
243 /* pre/post twiddle factors */ | 233 if (ff_mdct_init(&q->mdct_ctx, av_log2(mlt_size)+1, 1)) { |
244 for (j=0 ; j<q->mlt_size/2 ; j++){ | 234 av_free(q->mlt_window); |
245 q->mlt_precos[j] = cos( ((j+0.25)*M_PI)/q->mlt_size); | 235 return -1; |
246 q->mlt_presin[j] = sin( ((j+0.25)*M_PI)/q->mlt_size); | 236 } |
247 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 | 237 av_log(NULL,AV_LOG_DEBUG,"MDCT initialized, order = %d.\n", |
248 } | 238 av_log2(mlt_size)+1); |
249 | 239 |
250 /* Initialize the FFT. */ | 240 return 0; |
251 ff_fft_init(&q->fft_ctx, av_log2(q->mlt_size)-1, 0); | |
252 av_log(NULL,AV_LOG_DEBUG,"FFT initialized, order = %d.\n", | |
253 av_log2(q->samples_per_channel)-1); | |
254 | |
255 return (int)(q->mlt_window && q->mlt_precos && q->mlt_presin && q->mlt_postcos); | |
256 } | 241 } |
257 | 242 |
258 /*************** init functions end ***********/ | 243 /*************** init functions end ***********/ |
259 | 244 |
260 /** | 245 /** |
311 COOKContext *q = avctx->priv_data; | 296 COOKContext *q = avctx->priv_data; |
312 av_log(avctx,AV_LOG_DEBUG, "Deallocating memory.\n"); | 297 av_log(avctx,AV_LOG_DEBUG, "Deallocating memory.\n"); |
313 | 298 |
314 /* Free allocated memory buffers. */ | 299 /* Free allocated memory buffers. */ |
315 av_free(q->mlt_window); | 300 av_free(q->mlt_window); |
316 av_free(q->mlt_precos); | |
317 av_free(q->mlt_presin); | |
318 av_free(q->mlt_postcos); | |
319 av_free(q->decoded_bytes_buffer); | 301 av_free(q->decoded_bytes_buffer); |
320 | 302 |
321 /* Free the transform. */ | 303 /* Free the transform. */ |
322 ff_fft_end(&q->fft_ctx); | 304 ff_mdct_end(&q->mdct_ctx); |
323 | 305 |
324 /* Free the VLC tables. */ | 306 /* Free the VLC tables. */ |
325 for (i=0 ; i<13 ; i++) { | 307 for (i=0 ; i<13 ; i++) { |
326 free_vlc(&q->envelope_quant_index[i]); | 308 free_vlc(&q->envelope_quant_index[i]); |
327 } | 309 } |
712 * @param inbuffer pointer to the mltcoefficients | 694 * @param inbuffer pointer to the mltcoefficients |
713 * @param outbuffer pointer to the timedomain buffer | 695 * @param outbuffer pointer to the timedomain buffer |
714 * @param mlt_tmp pointer to temporary storage space | 696 * @param mlt_tmp pointer to temporary storage space |
715 */ | 697 */ |
716 | 698 |
717 static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer, | 699 static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer) |
718 float* mlt_tmp){ | 700 { |
719 int i; | 701 int i; |
720 | 702 |
721 /* prerotation */ | 703 q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, outbuffer, inbuffer, q->mdct_tmp); |
722 for(i=0 ; i<q->mlt_size ; i+=2){ | 704 |
723 outbuffer[i] = (q->mlt_presin[i/2] * inbuffer[q->mlt_size-1-i]) + | 705 for(i = 0; i < q->samples_per_channel; i++){ |
724 (q->mlt_precos[i/2] * inbuffer[i]); | 706 float tmp = outbuffer[i]; |
725 outbuffer[i+1] = (q->mlt_precos[i/2] * inbuffer[q->mlt_size-1-i]) - | 707 |
726 (q->mlt_presin[i/2] * inbuffer[i]); | 708 outbuffer[i] = q->mlt_window[i] * outbuffer[q->samples_per_channel + i]; |
727 } | 709 outbuffer[q->samples_per_channel + i] = q->mlt_window[q->samples_per_channel - 1 - i] * -tmp; |
728 | |
729 /* FFT */ | |
730 ff_fft_permute(&q->fft_ctx, (FFTComplex *) outbuffer); | |
731 ff_fft_calc (&q->fft_ctx, (FFTComplex *) outbuffer); | |
732 | |
733 /* postrotation */ | |
734 for(i=0 ; i<q->mlt_size ; i+=2){ | |
735 mlt_tmp[i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i+1]) + | |
736 (q->mlt_postcos[i/2] * outbuffer[i]); | |
737 mlt_tmp[q->mlt_size-1-i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i]) - | |
738 (q->mlt_postcos[i/2] * outbuffer[i+1]); | |
739 } | |
740 | |
741 /* window and reorder */ | |
742 for(i=0 ; i<q->mlt_size/2 ; i++){ | |
743 outbuffer[i] = mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[i]; | |
744 outbuffer[q->mlt_size-1-i]= mlt_tmp[q->mlt_size/2-1-i] * | |
745 q->mlt_window[q->mlt_size-1-i]; | |
746 outbuffer[q->mlt_size+i]= mlt_tmp[q->mlt_size/2+i] * | |
747 q->mlt_window[q->mlt_size-1-i]; | |
748 outbuffer[2*q->mlt_size-1-i]= -(mlt_tmp[q->mlt_size/2+i] * | |
749 q->mlt_window[i]); | |
750 } | 710 } |
751 } | 711 } |
752 | 712 |
753 | 713 |
754 /** | 714 /** |
942 cook_gains *gains, float *previous_buffer, | 902 cook_gains *gains, float *previous_buffer, |
943 int16_t *out, int chan) | 903 int16_t *out, int chan) |
944 { | 904 { |
945 int j; | 905 int j; |
946 | 906 |
947 cook_imlt(q, decode_buffer, q->mono_mdct_output, q->mlt_tmp); | 907 cook_imlt(q, decode_buffer, q->mono_mdct_output); |
948 gain_compensate(q, gains, previous_buffer); | 908 gain_compensate(q, gains, previous_buffer); |
949 | 909 |
950 /* Clip and convert floats to 16 bits. | 910 /* Clip and convert floats to 16 bits. |
951 */ | 911 */ |
952 for (j = 0; j < q->samples_per_channel; j++) { | 912 for (j = 0; j < q->samples_per_channel; j++) { |
1043 PRINT("sample_rate",q->sample_rate); | 1003 PRINT("sample_rate",q->sample_rate); |
1044 PRINT("samples_per_channel",q->samples_per_channel); | 1004 PRINT("samples_per_channel",q->samples_per_channel); |
1045 PRINT("samples_per_frame",q->samples_per_frame); | 1005 PRINT("samples_per_frame",q->samples_per_frame); |
1046 PRINT("subbands",q->subbands); | 1006 PRINT("subbands",q->subbands); |
1047 PRINT("random_state",q->random_state); | 1007 PRINT("random_state",q->random_state); |
1048 PRINT("mlt_size",q->mlt_size); | |
1049 PRINT("js_subband_start",q->js_subband_start); | 1008 PRINT("js_subband_start",q->js_subband_start); |
1050 PRINT("log2_numvector_size",q->log2_numvector_size); | 1009 PRINT("log2_numvector_size",q->log2_numvector_size); |
1051 PRINT("numvector_size",q->numvector_size); | 1010 PRINT("numvector_size",q->numvector_size); |
1052 PRINT("total_subbands",q->total_subbands); | 1011 PRINT("total_subbands",q->total_subbands); |
1053 } | 1012 } |
1143 return -1; | 1102 return -1; |
1144 break; | 1103 break; |
1145 } | 1104 } |
1146 | 1105 |
1147 /* Initialize variable relations */ | 1106 /* Initialize variable relations */ |
1148 q->mlt_size = q->samples_per_channel; | |
1149 q->numvector_size = (1 << q->log2_numvector_size); | 1107 q->numvector_size = (1 << q->log2_numvector_size); |
1150 | 1108 |
1151 /* Generate tables */ | 1109 /* Generate tables */ |
1152 init_rootpow2table(q); | 1110 init_rootpow2table(q); |
1153 init_pow2table(q); | 1111 init_pow2table(q); |
1181 q->gains1.previous = q->gain_2; | 1139 q->gains1.previous = q->gain_2; |
1182 q->gains2.now = q->gain_3; | 1140 q->gains2.now = q->gain_3; |
1183 q->gains2.previous = q->gain_4; | 1141 q->gains2.previous = q->gain_4; |
1184 | 1142 |
1185 /* Initialize transform. */ | 1143 /* Initialize transform. */ |
1186 if ( init_cook_mlt(q) == 0 ) | 1144 if ( init_cook_mlt(q) != 0 ) |
1187 return -1; | 1145 return -1; |
1188 | 1146 |
1189 /* Try to catch some obviously faulty streams, othervise it might be exploitable */ | 1147 /* Try to catch some obviously faulty streams, othervise it might be exploitable */ |
1190 if (q->total_subbands > 53) { | 1148 if (q->total_subbands > 53) { |
1191 av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n"); | 1149 av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n"); |