1/* 2 * fdct BlackFin 3 * 4 * Copyright (C) 2007 Marc Hoffman <marc.hoffman@analog.com> 5 * 6 * This file is part of FFmpeg. 7 * 8 * FFmpeg is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * FFmpeg is distributed in the hope that it will be useful, 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 19 * License along with FFmpeg; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22/* 23 void ff_bfin_fdct (DCTELEM *buf); 24 25 This implementation works only for 8x8 input. The range of input 26 must be -256 to 255 i.e. 8bit input represented in a 16bit data 27 word. The original data must be sign extended into the 16bit data 28 words. 29 30 31 Chen factorization of 32 33 8 34 X(m) = sum (x(n) * cos ((2n+1)*m*pi/16)) 35 n=0 36 37 C4 38 0 --*-------------*0+7---*-----*0+3-------*-*-------------------> 0 39 \ / \ / X S4,S4 40 1 --*-\---------/-*1+6---*-\-/-*1+2-------*-*-------------------> 4 41 \ / \ -C4 C3 42 2 --*---\-----/---*2+5---*-/-\-*1-2---------------*-*-----------> 2 43 \ / / \ X S3,-S3 44 3 --*-----\-/-----*3+4---*-----*0-3---------------*-*-----------> 6 45 / C7 C3 46 4 --*-----/-\-----*3-4------------*-*4+5--*-----*---------------> 1 47 / \ -C4 X \ /S7 C3 48 5 --*---/-----\---*2-5---*-*------*=*4-5----\-/------*-*--------> 5 49 / \ X S4,S4 / X S3,-S3 50 6 --*-/---------\-*1-6---*-*------*=*7-6----/-\------*-*--------> 3 51 / \ C4 X / \-S7 C3 52 --*-------------*0-7------------*-*7+6--*-----*---------------> 7 53 C7 54 55Notation 56 Cn = cos(n*pi/8) used throughout the code. 57 58 59 Registers used: 60 R0, R1, R2, R3, R4, R5, R6,R7, P0, P1, P2, P3, P4, P5, A0, A1. 61 Other registers used: 62 I0, I1, I2, I3, B0, B2, B3, M0, M1, L3 registers and LC0. 63 64 Input - r0 - pointer to start of DCTELEM *block 65 66 Output - The DCT output coefficients in the DCTELEM *block 67 68 Register constraint: 69 This code is called from jpeg_encode. 70 R6, R5, R4 if modified should be stored and restored. 71 72 73 Performance: (Timer version 0.6.33) 74 Code Size : 240 Bytes. 75 Memory Required : 76 Input Matrix : 8 * 8 * 2 Bytes. 77 Coefficients : 16 Bytes 78 Temporary matrix: 8 * 8 * 2 Bytes. 79 Cycle Count :26+{18+8*(14+2S)}*2 where S -> Stalls 80 (7.45 c/pel) 81 ----------------------------------------- 82 | Size | Forward DCT | Inverse DCT | 83 ----------------------------------------- 84 | 8x8 | 284 Cycles | 311 Cycles | 85 ----------------------------------------- 86 87Ck = int16(cos(k/16*pi)*32767+.5)/2 88#define C4 23170 89#define C3 13623 90#define C6 6270 91#define C7 3196 92 93Sk = int16(sin(k/16*pi)*32767+.5)/2 94#define S4 11585 95#define S3 9102 96#define S6 15137 97#define S7 16069 98 99the coefficients are ordered as follows: 100short dct_coef[] 101 C4,S4, 102 C6,S6, 103 C7,S7, 104 S3,C3, 105 106----------------------------------------------------------- 107FFMPEG conformance testing results 108----------------------------------------------------------- 109dct-test: modified with the following 110 dct_error("BFINfdct", 0, ff_bfin_fdct, fdct, test); 111produces the following output: 112 113root:/u/ffmpeg/bhead/libavcodec> ./dct-test 114ffmpeg DCT/IDCT test 115 116 2 -131 -6 -48 -36 33 -83 24 117 34 52 -24 -15 5 92 57 143 118 -67 -43 -1 74 -16 5 -71 32 119 -78 106 92 -34 -38 81 20 -18 120 7 -62 40 2 -15 90 -62 -83 121 -83 1 -104 -13 43 -19 7 11 122 -63 31 12 -29 83 72 21 10 123 -17 -63 -15 73 50 -91 159 -14 124DCT BFINfdct: err_inf=2 err2=0.16425938 syserr=0.00795000 maxout=2098 blockSumErr=27 125DCT BFINfdct: 92.1 kdct/s 126root:/u/ffmpeg/bhead/libavcodec> 127 128*/ 129 130#include "config_bfin.h" 131 132#ifdef __FDPIC__ 133.section .l1.data.B,"aw",@progbits 134#else 135.data 136#endif 137.align 4; 138dct_coeff: 139.short 0x5a82, 0x2d41, 0x187e, 0x3b21, 0x0c7c, 0x3ec5, 0x238e, 0x3537; 140 141#ifdef __FDPIC__ 142.section .l1.data.A,"aw",@progbits 143#endif 144.align 4 145vtmp: .space 128 146 147.text 148DEFUN(fdct,mL1, 149 (DCTELEM *block)): 150 [--SP] = (R7:4, P5:3); // Push the registers onto the stack. 151 152 b0 = r0; 153 RELOC(r0, P3, dct_coeff); 154 b3 = r0; 155 RELOC(r0, P3, vtmp); 156 b2 = r0; 157 158 L3 = 16; // L3 is set to 16 to make the coefficient 159 // array Circular. 160 161 162//---------------------------------------------------------------------------- 163 164/* 165 * I0, I1, and I2 registers are used to read the input data. I3 register is used 166 * to read the coefficients. P0 and P1 registers are used for writing the output 167 * data. 168 */ 169 M0 = 12 (X); // All these initializations are used in the 170 M1 = 16 (X); // modification of address offsets. 171 172 M2 = 128 (X); 173 174 P2 = 16; 175 P3 = 32 (X); 176 P4 = -110 (X); 177 P5 = -62 (X); 178 P0 = 2(X); 179 180 181 // Prescale the input to get the correct precision. 182 i0=b0; 183 i1=b0; 184 185 lsetup (.0, .1) LC0 = P3; 186 r0=[i0++]; 187.0: r1=r0<<3 (v) || r0=[i0++] ; 188.1: [i1++]=r1; 189 190 /* 191 * B0 points to the "in" buffer. 192 * B2 points to "temp" buffer in the first iteration. 193 */ 194 195 lsetup (.2, .3) LC0 = P0; 196.2: 197 I0 = B0; // I0 points to Input Element (0, 0). 198 I1 = B0; // Element 1 and 0 is read in R0. 199 I1 += M0 || R0 = [I0++]; // I1 points to Input Element (0, 6). 200 I2 = I1; // Element 6 is read into R3.H. 201 I2 -= 4 || R3.H = W[I1++]; // I2 points to Input Element (0, 4). 202 203 I3 = B3; // I3 points to Coefficients. 204 P0 = B2; // P0 points to temporary array Element 205 // (0, 0). 206 P1 = B2; // P1 points to temporary array. 207 R7 = [P1++P2] || R2 = [I2++]; // P1 points to temporary array 208 // Element (1, 0). 209 // R7 is a dummy read. X4,X5 210 // are read into R2. 211 R3.L = W[I1--]; // X7 is read into R3.L. 212 R1.H = W[I0++]; // X2 is read into R1.H. 213 214 215 /* 216 * X0 = (X0 + X7) / 2. 217 * X1 = (X1 + X6) / 2. 218 * X6 = (X1 - X6) / 2. 219 * X7 = (X0 - X7) / 2. 220 * It reads the data 3 in R1.L. 221 */ 222 223 R0 = R0 +|+ R3, R3 = R0 -|- R3 || R1.L = W[I0++] || NOP; 224 225 /* 226 * X2 = (X2 + X5) / 2. 227 * X3 = (X3 + X4) / 2. 228 * X4 = (X3 - X4) / 2. 229 * X5 = (X2 - X5) / 2. 230 * R7 = C4 = cos(4*pi/16) 231 */ 232 233 R1 = R1 +|+ R2, R2 = R1 -|- R2 (CO) || NOP || R7 = [I3++]; 234 235 /* 236 * At the end of stage 1 R0 has (1,0), R1 has (2,3), R2 has (4, 5) and 237 * R3 has (6,7). 238 * Where the notation (x, y) represents uper/lower half pairs. 239 */ 240 241 /* 242 * X0 = X0 + X3. 243 * X1 = X1 + X2. 244 * X2 = X1 - X2. 245 * X3 = X0 - X3. 246 */ 247 R0 = R0 +|+ R1, R1 = R0 -|- R1; 248 249 lsetup (.row0, .row1) LC1 = P2 >> 1; // 1d dct, loops 8x 250.row0: 251 252 /* 253 * This is part 2 computation continued..... 254 * A1 = X6 * cos(pi/4) 255 * A0 = X6 * cos(pi/4) 256 * A1 = A1 - X5 * cos(pi/4) 257 * A0 = A0 + X5 * cos(pi/4). 258 * The instruction W[I0] = R3.L is used for packing it to R2.L. 259 */ 260 261 A1=R3.H*R7.l, A0=R3.H*R7.l || I1+=M1 || W[I0] = R3.L; 262 R4.H=(A1-=R2.L*R7.l), R4.L=(A0+=R2.L*R7.l) || I2+=M0 || NOP; 263 264 /* R0 = (X1,X0) R1 = (X2,X3) R4 = (X5, X6). */ 265 266 /* 267 * A1 = X0 * cos(pi/4) 268 * A0 = X0 * cos(pi/4) 269 * A1 = A1 - X1 * cos(pi/4) 270 * A0 = A0 + X1 * cos(pi/4) 271 * R7 = (C2,C6) 272 */ 273 A1=R0.L*R7.h, A0=R0.L*R7.h || NOP || R3.H=W[I1++]; 274 R5.H=(A1-=R0.H*R7.h),R5.L=(A0+=R0.H*R7.h) || R7=[I3++] || NOP; 275 276 /* 277 * A1 = X2 * cos(3pi/8) 278 * A0 = X3 * cos(3pi/8) 279 * A1 = A1 + X3 * cos(pi/8) 280 * A0 = A0 - X2 * cos(pi/8) 281 * R3 = cos(pi/4) 282 * R7 = (cos(7pi/8),cos(pi/8)) 283 * X4 = X4 + X5. 284 * X5 = X4 - X5. 285 * X6 = X7 - X6. 286 * X7 = X7 + X6. 287 */ 288 A1=R1.H*R7.L, A0=R1.L*R7.L || W[P0++P3]=R5.L || R2.L=W[I0]; 289 R2=R2+|+R4, R4=R2-|-R4 || I0+=4 || R3.L=W[I1--]; 290 R6.H=(A1+=R1.L*R7.H),R6.L=(A0 -= R1.H * R7.H) || I0+=4 || R7=[I3++]; 291 292 /* R2 = (X4, X7) R4 = (X5,X6) R5 = (X1, X0) R6 = (X2,X3). */ 293 294 /* 295 * A1 = X4 * cos(7pi/16) 296 * A0 = X7 * cos(7pi/16) 297 * A1 = A1 + X7 * cos(pi/16) 298 * A0 = A0 - X4 * cos(pi/16) 299 */ 300 301 A1=R2.H*R7.L, A0=R2.L*R7.L || W[P0++P3]=R6.H || R0=[I0++]; 302 R2.H=(A1+=R2.L*R7.H),R2.L=(A0-=R2.H*R7.H) || W[P0++P3]=R5.H || R7=[I3++]; 303 304 /* 305 * A1 = X5 * cos(3pi/16) 306 * A0 = X6 * cos(3pi/16) 307 * A1 = A1 + X6 * cos(5pi/16) 308 * A0 = A0 - X5 * cos(5pi/16) 309 * The output values are written. 310 */ 311 312 A1=R4.H*R7.H, A0=R4.L*R7.H || W[P0++P2]=R6.L || R1.H=W[I0++]; 313 R4.H=(A1+=R4.L*R7.L),R4.L=(A0-=R4.H*R7.L) || W[P0++P4]=R2.L || R1.L=W[I0++]; 314 315 316 /* Beginning of next stage, **pipelined** + drain and store the 317 rest of the column store. */ 318 319 R0=R0+|+R3,R3=R0-|-R3 || W[P1++P3]=R2.H || R2=[I2++]; 320 R1=R1+|+R2,R2=R1-|-R2 (CO) || W[P1++P3]=R4.L || R7=[I3++]; 321.row1: R0=R0+|+R1,R1=R0-|-R1 || W[P1++P5]=R4.H || NOP; 322 323 // Exchange input with output. 324 B1 = B0; 325 B0 = B2; 326.3: B2 = B1; 327 328 L3=0; 329 (r7:4,p5:3) = [sp++]; 330 RTS; 331DEFUN_END(fdct) 332 333