| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * (I)DCT Transforms | 
					
						
							|  |  |  |  * Copyright (c) 2009 Peter Ross <pross@xvid.org> | 
					
						
							|  |  |  |  * Copyright (c) 2010 Alex Converse <alex.converse@gmail.com> | 
					
						
							|  |  |  |  * Copyright (c) 2010 Vitor Sessak | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							|  |  |  |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2010-04-20 14:45:34 +00:00
										 |  |  |  * @file | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  |  * (Inverse) Discrete Cosine Transforms. These are also known as the | 
					
						
							|  |  |  |  * type II and type III DCTs respectively. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							| 
									
										
										
										
											2010-03-06 14:34:46 +00:00
										 |  |  | #include "libavutil/mathematics.h"
 | 
					
						
							| 
									
										
										
										
											2011-03-20 02:14:25 +00:00
										 |  |  | #include "dct.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-17 11:48:28 +01:00
										 |  |  | #include "dct32.h"
 | 
					
						
							| 
									
										
										
										
											2010-06-30 20:11:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | /* sin((M_PI * x / (2*n)) */ | 
					
						
							|  |  |  | #define SIN(s,n,x) (s->costab[(n) - (x)])
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* cos((M_PI * x / (2*n)) */ | 
					
						
							|  |  |  | #define COS(s,n,x) (s->costab[x])
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-23 19:48:16 +00:00
										 |  |  | static void ff_dst_calc_I_c(DCTContext *ctx, FFTSample *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int n = 1 << ctx->nbits; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     data[0] = 0; | 
					
						
							|  |  |  |     for(i = 1; i < n/2; i++) { | 
					
						
							|  |  |  |         float tmp1 = data[i    ]; | 
					
						
							|  |  |  |         float tmp2 = data[n - i]; | 
					
						
							|  |  |  |         float s = SIN(ctx, n, 2*i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s *= tmp1 + tmp2; | 
					
						
							|  |  |  |         tmp1 = (tmp1 - tmp2) * 0.5f; | 
					
						
							|  |  |  |         data[i    ] = s + tmp1; | 
					
						
							|  |  |  |         data[n - i] = s - tmp1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     data[n/2] *= 2; | 
					
						
							| 
									
										
										
										
											2011-03-19 15:14:17 +00:00
										 |  |  |     ctx->rdft.rdft_calc(&ctx->rdft, data); | 
					
						
							| 
									
										
										
										
											2010-03-23 19:48:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     data[0] *= 0.5f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(i = 1; i < n-2; i += 2) { | 
					
						
							|  |  |  |         data[i + 1] += data[i - 1]; | 
					
						
							|  |  |  |         data[i    ] = -data[i + 2]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     data[n-1] = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ff_dct_calc_I_c(DCTContext *ctx, FFTSample *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int n = 1 << ctx->nbits; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     float next = -0.5f * (data[0] - data[n]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(i = 0; i < n/2; i++) { | 
					
						
							|  |  |  |         float tmp1 = data[i    ]; | 
					
						
							|  |  |  |         float tmp2 = data[n - i]; | 
					
						
							|  |  |  |         float s = SIN(ctx, n, 2*i); | 
					
						
							|  |  |  |         float c = COS(ctx, n, 2*i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c *= tmp1 - tmp2; | 
					
						
							|  |  |  |         s *= tmp1 - tmp2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         next += c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tmp1 = (tmp1 + tmp2) * 0.5f; | 
					
						
							|  |  |  |         data[i    ] = tmp1 - s; | 
					
						
							|  |  |  |         data[n - i] = tmp1 + s; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-19 15:14:17 +00:00
										 |  |  |     ctx->rdft.rdft_calc(&ctx->rdft, data); | 
					
						
							| 
									
										
										
										
											2010-03-23 19:48:16 +00:00
										 |  |  |     data[n] = data[1]; | 
					
						
							|  |  |  |     data[1] = next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(i = 3; i <= n; i += 2) | 
					
						
							|  |  |  |         data[i] = data[i - 2] - data[i]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:35:05 +00:00
										 |  |  | static void ff_dct_calc_III_c(DCTContext *ctx, FFTSample *data) | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     int n = 1 << ctx->nbits; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     float next = data[n - 1]; | 
					
						
							|  |  |  |     float inv_n = 1.0f / n; | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     for (i = n - 2; i >= 2; i -= 2) { | 
					
						
							|  |  |  |         float val1 = data[i    ]; | 
					
						
							|  |  |  |         float val2 = data[i - 1] - data[i + 1]; | 
					
						
							|  |  |  |         float c = COS(ctx, n, i); | 
					
						
							|  |  |  |         float s = SIN(ctx, n, i); | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |         data[i    ] = c * val1 + s * val2; | 
					
						
							|  |  |  |         data[i + 1] = s * val1 - c * val2; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     data[1] = 2 * next; | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-19 15:14:17 +00:00
										 |  |  |     ctx->rdft.rdft_calc(&ctx->rdft, data); | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     for (i = 0; i < n / 2; i++) { | 
					
						
							|  |  |  |         float tmp1 = data[i        ] * inv_n; | 
					
						
							|  |  |  |         float tmp2 = data[n - i - 1] * inv_n; | 
					
						
							|  |  |  |         float csc = ctx->csc2[i] * (tmp1 - tmp2); | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |         tmp1 += tmp2; | 
					
						
							|  |  |  |         data[i        ] = tmp1 + csc; | 
					
						
							|  |  |  |         data[n - i - 1] = tmp1 - csc; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-03-21 11:35:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ff_dct_calc_II_c(DCTContext *ctx, FFTSample *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int n = 1 << ctx->nbits; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     float next; | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     for (i=0; i < n/2; i++) { | 
					
						
							|  |  |  |         float tmp1 = data[i        ]; | 
					
						
							|  |  |  |         float tmp2 = data[n - i - 1]; | 
					
						
							|  |  |  |         float s = SIN(ctx, n, 2*i + 1); | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |         s *= tmp1 - tmp2; | 
					
						
							|  |  |  |         tmp1 = (tmp1 + tmp2) * 0.5f; | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |         data[i    ] = tmp1 + s; | 
					
						
							|  |  |  |         data[n-i-1] = tmp1 - s; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-19 15:14:17 +00:00
										 |  |  |     ctx->rdft.rdft_calc(&ctx->rdft, data); | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     next = data[1] * 0.5; | 
					
						
							|  |  |  |     data[1] *= -1; | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |     for (i = n - 2; i >= 0; i -= 2) { | 
					
						
							|  |  |  |         float inr = data[i    ]; | 
					
						
							|  |  |  |         float ini = data[i + 1]; | 
					
						
							|  |  |  |         float c = COS(ctx, n, i); | 
					
						
							|  |  |  |         float s = SIN(ctx, n, i); | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |         data[i  ] = c * inr + s * ini; | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:36:17 +00:00
										 |  |  |         data[i+1] = next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         next +=     s * inr - c * ini; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 20:11:27 +00:00
										 |  |  | static void dct32_func(DCTContext *ctx, FFTSample *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ctx->dct32(data, data); | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-23 19:48:16 +00:00
										 |  |  | av_cold int ff_dct_init(DCTContext *s, int nbits, enum DCTTransformType inverse) | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     int n = 1 << nbits; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:04 +01:00
										 |  |  |     memset(s, 0, sizeof(*s)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  |     s->nbits    = nbits; | 
					
						
							|  |  |  |     s->inverse  = inverse; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:04 +01:00
										 |  |  |     if (inverse == DCT_II && nbits == 5) { | 
					
						
							|  |  |  |         s->dct_calc = dct32_func; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:36 +01:00
										 |  |  |         ff_init_ff_cos_tabs(nbits+2); | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:36 +01:00
										 |  |  |         s->costab = ff_cos_tabs[nbits+2]; | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:36 +01:00
										 |  |  |         s->csc2 = av_malloc(n/2 * sizeof(FFTSample)); | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:36 +01:00
										 |  |  |         if (ff_rdft_init(&s->rdft, nbits, inverse == DCT_III) < 0) { | 
					
						
							|  |  |  |             av_free(s->csc2); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:36 +01:00
										 |  |  |         for (i = 0; i < n/2; i++) | 
					
						
							|  |  |  |             s->csc2[i] = 0.5 / sin((M_PI / (2*n) * (2*i + 1))); | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-16 15:57:36 +01:00
										 |  |  |         switch(inverse) { | 
					
						
							|  |  |  |         case DCT_I  : s->dct_calc = ff_dct_calc_I_c; break; | 
					
						
							|  |  |  |         case DCT_II : s->dct_calc = ff_dct_calc_II_c ; break; | 
					
						
							|  |  |  |         case DCT_III: s->dct_calc = ff_dct_calc_III_c; break; | 
					
						
							|  |  |  |         case DST_I  : s->dct_calc = ff_dst_calc_I_c; break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-03-23 19:48:16 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-30 20:11:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-17 11:48:28 +01:00
										 |  |  |     s->dct32 = ff_dct32_float; | 
					
						
							| 
									
										
										
										
											2010-07-06 16:58:54 +00:00
										 |  |  |     if (HAVE_MMX)     ff_dct_init_mmx(s); | 
					
						
							| 
									
										
										
										
											2010-06-30 20:11:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-21 11:28:38 +00:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 00:39:47 +00:00
										 |  |  | av_cold void ff_dct_end(DCTContext *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ff_rdft_end(&s->rdft); | 
					
						
							|  |  |  |     av_free(s->csc2); | 
					
						
							|  |  |  | } |