9308
|
1 /*
|
|
2 * reference discrete cosine transform (double precision)
|
|
3 * Copyright (C) 2009 Dylan Yudaken
|
|
4 *
|
|
5 * This file is part of FFmpeg.
|
|
6 *
|
|
7 * FFmpeg is free software; you can redistribute it and/or
|
|
8 * modify it under the terms of the GNU Lesser General Public
|
|
9 * License as published by the Free Software Foundation; either
|
|
10 * version 2.1 of the License, or (at your option) any later version.
|
|
11 *
|
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15 * Lesser General Public License for more details.
|
|
16 *
|
|
17 * You should have received a copy of the GNU Lesser General Public
|
|
18 * License along with FFmpeg; if not, write to the Free Software
|
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
20 */
|
|
21
|
|
22 /**
|
|
23 * @file libavcodec/dctref.c
|
|
24 * reference discrete cosine transform (double precision)
|
|
25 *
|
|
26 * @author Dylan Yudaken (dyudaken at gmail)
|
|
27 *
|
|
28 * @note This file could be optimized a lot, but is for
|
|
29 * reference and so readability is better.
|
|
30 */
|
|
31
|
|
32 #include "libavutil/mathematics.h"
|
|
33 static double coefficients[8 * 8];
|
|
34
|
|
35 /**
|
|
36 * Initialize the double precision discrete cosine transform
|
|
37 * functions fdct & idct.
|
|
38 */
|
|
39 av_cold void ff_ref_dct_init(void)
|
|
40 {
|
|
41 unsigned int i, j;
|
|
42
|
|
43 for (j = 0; j < 8; ++j) {
|
|
44 coefficients[j] = sqrt(0.125);
|
|
45 for (i = 8; i < 64; i += 8) {
|
|
46 coefficients[i + j] = 0.5 * cos(i * (j + 0.5) * M_PI / 64.0);
|
|
47 }
|
|
48 }
|
|
49 }
|
|
50
|
|
51 /**
|
|
52 * Transform 8x8 block of data with a double precision forward DCT <br>
|
|
53 * This is a reference implementation.
|
|
54 *
|
|
55 * @param block pointer to 8x8 block of data to transform
|
|
56 */
|
|
57 void ff_ref_fdct(short *block)
|
|
58 {
|
|
59 /* implement the equation: block = coefficients * block * coefficients' */
|
|
60
|
|
61 unsigned int i, j, k;
|
|
62 double out[8 * 8];
|
|
63
|
|
64 /* out = coefficients * block */
|
|
65 for (i = 0; i < 64; i += 8) {
|
|
66 for (j = 0; j < 8; ++j) {
|
|
67 double tmp = 0;
|
|
68 for (k = 0; k < 8; ++k) {
|
|
69 tmp += coefficients[i + k] * block[k * 8 + j];
|
|
70 }
|
|
71 out[i + j] = tmp * 8;
|
|
72 }
|
|
73 }
|
|
74
|
|
75 /* block = out * (coefficients') */
|
|
76 for (j = 0; j < 8; ++j) {
|
|
77 for (i = 0; i < 64; i += 8) {
|
|
78 double tmp = 0;
|
|
79 for (k = 0; k < 8; ++k) {
|
|
80 tmp += out[i + k] * coefficients[j * 8 + k];
|
|
81 }
|
|
82 block[i + j] = floor(tmp + 0.499999999999);
|
|
83 }
|
|
84 }
|
|
85 }
|
|
86
|
|
87 /**
|
|
88 * Transform 8x8 block of data with a double precision inverse DCT <br>
|
|
89 * This is a reference implementation.
|
|
90 *
|
|
91 * @param block pointer to 8x8 block of data to transform
|
|
92 */
|
|
93 void ff_ref_idct(short *block)
|
|
94 {
|
|
95 /* implement the equation: block = (coefficients') * block * coefficients */
|
|
96
|
|
97 unsigned int i, j, k;
|
|
98 double out[8 * 8];
|
|
99
|
|
100 /* out = block * coefficients */
|
|
101 for (i = 0; i < 64; i += 8) {
|
|
102 for (j = 0; j < 8; ++j) {
|
|
103 double tmp = 0;
|
|
104 for (k = 0; k < 8; ++k) {
|
|
105 tmp += block[i + k] * coefficients[k * 8 + j];
|
|
106 }
|
|
107 out[i + j] = tmp;
|
|
108 }
|
|
109 }
|
|
110
|
|
111 /* block = (coefficients') * out */
|
|
112 for (i = 0; i < 8; ++i) {
|
|
113 for (j = 0; j < 8; ++j) {
|
|
114 double tmp = 0;
|
|
115 for (k = 0; k < 64; k += 8) {
|
|
116 tmp += coefficients[k + i] * out[k + j];
|
|
117 }
|
|
118 block[i * 8 + j] = floor(tmp + 0.5);
|
|
119 }
|
|
120 }
|
|
121 }
|