1/* 2 * Copyright (c) 2009 David Conrad 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include "libavutil/arm/asm.S" 22 23const vp3_idct_constants, align=4 24.short 64277, 60547, 54491, 46341, 36410, 25080, 12785 25endconst 26 27#define xC1S7 d0[0] 28#define xC2S6 d0[1] 29#define xC3S5 d0[2] 30#define xC4S4 d0[3] 31#define xC5S3 d1[0] 32#define xC6S2 d1[1] 33#define xC7S1 d1[2] 34 35.macro vp3_loop_filter 36 vsubl.u8 q3, d18, d17 37 vsubl.u8 q2, d16, d19 38 vadd.i16 q1, q3, q3 39 vadd.i16 q2, q2, q3 40 vadd.i16 q0, q1, q2 41 vrshr.s16 q0, q0, #3 42 vmovl.u8 q9, d18 43 vdup.u16 q15, r2 44 45 vabs.s16 q1, q0 46 vshr.s16 q0, q0, #15 47 vqsub.u16 q2, q15, q1 48 vqsub.u16 q3, q2, q1 49 vsub.i16 q1, q2, q3 50 veor q1, q1, q0 51 vsub.i16 q0, q1, q0 52 53 vaddw.u8 q2, q0, d17 54 vsub.i16 q3, q9, q0 55 vqmovun.s16 d0, q2 56 vqmovun.s16 d1, q3 57.endm 58 59function ff_vp3_v_loop_filter_neon, export=1 60 sub ip, r0, r1 61 sub r0, r0, r1, lsl #1 62 vld1.64 {d16}, [r0,:64], r1 63 vld1.64 {d17}, [r0,:64], r1 64 vld1.64 {d18}, [r0,:64], r1 65 vld1.64 {d19}, [r0,:64], r1 66 ldrb r2, [r2, #129*4] 67 68 vp3_loop_filter 69 70 vst1.64 {d0}, [ip,:64], r1 71 vst1.64 {d1}, [ip,:64], r1 72 bx lr 73endfunc 74 75function ff_vp3_h_loop_filter_neon, export=1 76 sub ip, r0, #1 77 sub r0, r0, #2 78 vld1.32 {d16[]}, [r0], r1 79 vld1.32 {d17[]}, [r0], r1 80 vld1.32 {d18[]}, [r0], r1 81 vld1.32 {d19[]}, [r0], r1 82 vld1.32 {d16[1]}, [r0], r1 83 vld1.32 {d17[1]}, [r0], r1 84 vld1.32 {d18[1]}, [r0], r1 85 vld1.32 {d19[1]}, [r0], r1 86 ldrb r2, [r2, #129*4] 87 88 vtrn.8 d16, d17 89 vtrn.8 d18, d19 90 vtrn.16 d16, d18 91 vtrn.16 d17, d19 92 93 vp3_loop_filter 94 95 vtrn.8 d0, d1 96 97 vst1.16 {d0[0]}, [ip], r1 98 vst1.16 {d1[0]}, [ip], r1 99 vst1.16 {d0[1]}, [ip], r1 100 vst1.16 {d1[1]}, [ip], r1 101 vst1.16 {d0[2]}, [ip], r1 102 vst1.16 {d1[2]}, [ip], r1 103 vst1.16 {d0[3]}, [ip], r1 104 vst1.16 {d1[3]}, [ip], r1 105 bx lr 106endfunc 107 108 109function vp3_idct_start_neon 110 vpush {d8-d15} 111 vmov.i16 q4, #0 112 vmov.i16 q5, #0 113 movrel r3, vp3_idct_constants 114 vld1.64 {d0-d1}, [r3,:128] 115 vld1.64 {d16-d19}, [r2,:128] 116 vst1.64 {q4-q5}, [r2,:128]! 117 vld1.64 {d20-d23}, [r2,:128] 118 vst1.64 {q4-q5}, [r2,:128]! 119 vld1.64 {d24-d27}, [r2,:128] 120 vst1.64 {q4-q5}, [r2,:128]! 121 vadd.s16 q1, q8, q12 122 vsub.s16 q8, q8, q12 123 vld1.64 {d28-d31}, [r2,:128] 124 vst1.64 {q4-q5}, [r2,:128]! 125 126vp3_idct_core_neon: 127 vmull.s16 q2, d18, xC1S7 // (ip[1] * C1) << 16 128 vmull.s16 q3, d19, xC1S7 129 vmull.s16 q4, d2, xC4S4 // ((ip[0] + ip[4]) * C4) << 16 130 vmull.s16 q5, d3, xC4S4 131 vmull.s16 q6, d16, xC4S4 // ((ip[0] - ip[4]) * C4) << 16 132 vmull.s16 q7, d17, xC4S4 133 vshrn.s32 d4, q2, #16 134 vshrn.s32 d5, q3, #16 135 vshrn.s32 d6, q4, #16 136 vshrn.s32 d7, q5, #16 137 vshrn.s32 d8, q6, #16 138 vshrn.s32 d9, q7, #16 139 vadd.s16 q12, q1, q3 // E = (ip[0] + ip[4]) * C4 140 vadd.s16 q8, q8, q4 // F = (ip[0] - ip[4]) * C4 141 vadd.s16 q1, q2, q9 // ip[1] * C1 142 143 vmull.s16 q2, d30, xC1S7 // (ip[7] * C1) << 16 144 vmull.s16 q3, d31, xC1S7 145 vmull.s16 q4, d30, xC7S1 // (ip[7] * C7) << 16 146 vmull.s16 q5, d31, xC7S1 147 vmull.s16 q6, d18, xC7S1 // (ip[1] * C7) << 16 148 vmull.s16 q7, d19, xC7S1 149 vshrn.s32 d4, q2, #16 150 vshrn.s32 d5, q3, #16 151 vshrn.s32 d6, q4, #16 // ip[7] * C7 152 vshrn.s32 d7, q5, #16 153 vshrn.s32 d8, q6, #16 // ip[1] * C7 154 vshrn.s32 d9, q7, #16 155 vadd.s16 q2, q2, q15 // ip[7] * C1 156 vadd.s16 q9, q1, q3 // A = ip[1] * C1 + ip[7] * C7 157 vsub.s16 q15, q4, q2 // B = ip[1] * C7 - ip[7] * C1 158 159 vmull.s16 q2, d22, xC5S3 // (ip[3] * C5) << 16 160 vmull.s16 q3, d23, xC5S3 161 vmull.s16 q4, d22, xC3S5 // (ip[3] * C3) << 16 162 vmull.s16 q5, d23, xC3S5 163 vmull.s16 q6, d26, xC5S3 // (ip[5] * C5) << 16 164 vmull.s16 q7, d27, xC5S3 165 vshrn.s32 d4, q2, #16 166 vshrn.s32 d5, q3, #16 167 vshrn.s32 d6, q4, #16 168 vshrn.s32 d7, q5, #16 169 vshrn.s32 d8, q6, #16 170 vshrn.s32 d9, q7, #16 171 vadd.s16 q3, q3, q11 // ip[3] * C3 172 vadd.s16 q4, q4, q13 // ip[5] * C5 173 vadd.s16 q1, q2, q11 // ip[3] * C5 174 vadd.s16 q11, q3, q4 // C = ip[3] * C3 + ip[5] * C5 175 176 vmull.s16 q2, d26, xC3S5 // (ip[5] * C3) << 16 177 vmull.s16 q3, d27, xC3S5 178 vmull.s16 q4, d20, xC2S6 // (ip[2] * C2) << 16 179 vmull.s16 q5, d21, xC2S6 180 vmull.s16 q6, d28, xC6S2 // (ip[6] * C6) << 16 181 vmull.s16 q7, d29, xC6S2 182 vshrn.s32 d4, q2, #16 183 vshrn.s32 d5, q3, #16 184 vshrn.s32 d6, q4, #16 185 vshrn.s32 d7, q5, #16 186 vshrn.s32 d8, q6, #16 // ip[6] * C6 187 vshrn.s32 d9, q7, #16 188 vadd.s16 q2, q2, q13 // ip[5] * C3 189 vadd.s16 q3, q3, q10 // ip[2] * C2 190 vsub.s16 q13, q2, q1 // D = ip[5] * C3 - ip[3] * C5 191 vsub.s16 q1, q9, q11 // (A - C) 192 vadd.s16 q11, q9, q11 // Cd = A + C 193 vsub.s16 q9, q15, q13 // (B - D) 194 vadd.s16 q13, q15, q13 // Dd = B + D 195 vadd.s16 q15, q3, q4 // G = ip[2] * C2 + ip[6] * C6 196 197 vmull.s16 q2, d2, xC4S4 // ((A - C) * C4) << 16 198 vmull.s16 q3, d3, xC4S4 199 vmull.s16 q4, d28, xC2S6 // (ip[6] * C2) << 16 200 vmull.s16 q5, d29, xC2S6 201 vmull.s16 q6, d20, xC6S2 // (ip[2] * C6) << 16 202 vmull.s16 q7, d21, xC6S2 203 vshrn.s32 d4, q2, #16 204 vshrn.s32 d5, q3, #16 205 vshrn.s32 d6, q4, #16 206 vshrn.s32 d7, q5, #16 207 vshrn.s32 d8, q6, #16 // ip[2] * C6 208 vmull.s16 q5, d18, xC4S4 // ((B - D) * C4) << 16 209 vmull.s16 q6, d19, xC4S4 210 vshrn.s32 d9, q7, #16 211 vadd.s16 q3, q3, q14 // ip[6] * C2 212 vadd.s16 q10, q1, q2 // Ad = (A - C) * C4 213 vsub.s16 q14, q4, q3 // H = ip[2] * C6 - ip[6] * C2 214 bx lr 215endfunc 216 217.macro VP3_IDCT_END type 218function vp3_idct_end_\type\()_neon 219.ifc \type, col 220 vdup.16 q0, r3 221 vadd.s16 q12, q12, q0 222 vadd.s16 q8, q8, q0 223.endif 224 225 vshrn.s32 d2, q5, #16 226 vshrn.s32 d3, q6, #16 227 vadd.s16 q2, q12, q15 // Gd = E + G 228 vadd.s16 q9, q1, q9 // (B - D) * C4 229 vsub.s16 q12, q12, q15 // Ed = E - G 230 vsub.s16 q3, q8, q10 // Fd = F - Ad 231 vadd.s16 q10, q8, q10 // Add = F + Ad 232 vadd.s16 q4, q9, q14 // Hd = Bd + H 233 vsub.s16 q14, q9, q14 // Bdd = Bd - H 234 vadd.s16 q8, q2, q11 // [0] = Gd + Cd 235 vsub.s16 q15, q2, q11 // [7] = Gd - Cd 236 vadd.s16 q9, q10, q4 // [1] = Add + Hd 237 vsub.s16 q10, q10, q4 // [2] = Add - Hd 238 vadd.s16 q11, q12, q13 // [3] = Ed + Dd 239 vsub.s16 q12, q12, q13 // [4] = Ed - Dd 240.ifc \type, row 241 vtrn.16 q8, q9 242.endif 243 vadd.s16 q13, q3, q14 // [5] = Fd + Bdd 244 vsub.s16 q14, q3, q14 // [6] = Fd - Bdd 245 246.ifc \type, row 247 // 8x8 transpose 248 vtrn.16 q10, q11 249 vtrn.16 q12, q13 250 vtrn.16 q14, q15 251 vtrn.32 q8, q10 252 vtrn.32 q9, q11 253 vtrn.32 q12, q14 254 vtrn.32 q13, q15 255 vswp d17, d24 256 vswp d19, d26 257 vadd.s16 q1, q8, q12 258 vswp d21, d28 259 vsub.s16 q8, q8, q12 260 vswp d23, d30 261.endif 262 bx lr 263endfunc 264.endm 265 266VP3_IDCT_END row 267VP3_IDCT_END col 268 269function ff_vp3_idct_put_neon, export=1 270 mov ip, lr 271 bl vp3_idct_start_neon 272 bl vp3_idct_end_row_neon 273 mov r3, #8 274 add r3, r3, #2048 // convert signed pixel to unsigned 275 bl vp3_idct_core_neon 276 bl vp3_idct_end_col_neon 277 mov lr, ip 278 vpop {d8-d15} 279 280 vqshrun.s16 d0, q8, #4 281 vqshrun.s16 d1, q9, #4 282 vqshrun.s16 d2, q10, #4 283 vqshrun.s16 d3, q11, #4 284 vst1.64 {d0}, [r0,:64], r1 285 vqshrun.s16 d4, q12, #4 286 vst1.64 {d1}, [r0,:64], r1 287 vqshrun.s16 d5, q13, #4 288 vst1.64 {d2}, [r0,:64], r1 289 vqshrun.s16 d6, q14, #4 290 vst1.64 {d3}, [r0,:64], r1 291 vqshrun.s16 d7, q15, #4 292 vst1.64 {d4}, [r0,:64], r1 293 vst1.64 {d5}, [r0,:64], r1 294 vst1.64 {d6}, [r0,:64], r1 295 vst1.64 {d7}, [r0,:64], r1 296 bx lr 297endfunc 298 299function ff_vp3_idct_add_neon, export=1 300 mov ip, lr 301 bl vp3_idct_start_neon 302 bl vp3_idct_end_row_neon 303 mov r3, #8 304 bl vp3_idct_core_neon 305 bl vp3_idct_end_col_neon 306 mov lr, ip 307 vpop {d8-d15} 308 mov r2, r0 309 310 vld1.64 {d0}, [r0,:64], r1 311 vshr.s16 q8, q8, #4 312 vld1.64 {d1}, [r0,:64], r1 313 vshr.s16 q9, q9, #4 314 vld1.64 {d2}, [r0,:64], r1 315 vaddw.u8 q8, q8, d0 316 vld1.64 {d3}, [r0,:64], r1 317 vaddw.u8 q9, q9, d1 318 vld1.64 {d4}, [r0,:64], r1 319 vshr.s16 q10, q10, #4 320 vld1.64 {d5}, [r0,:64], r1 321 vshr.s16 q11, q11, #4 322 vld1.64 {d6}, [r0,:64], r1 323 vqmovun.s16 d0, q8 324 vld1.64 {d7}, [r0,:64], r1 325 vqmovun.s16 d1, q9 326 vaddw.u8 q10, q10, d2 327 vaddw.u8 q11, q11, d3 328 vshr.s16 q12, q12, #4 329 vshr.s16 q13, q13, #4 330 vqmovun.s16 d2, q10 331 vqmovun.s16 d3, q11 332 vaddw.u8 q12, q12, d4 333 vaddw.u8 q13, q13, d5 334 vshr.s16 q14, q14, #4 335 vshr.s16 q15, q15, #4 336 vst1.64 {d0}, [r2,:64], r1 337 vqmovun.s16 d4, q12 338 vst1.64 {d1}, [r2,:64], r1 339 vqmovun.s16 d5, q13 340 vst1.64 {d2}, [r2,:64], r1 341 vaddw.u8 q14, q14, d6 342 vst1.64 {d3}, [r2,:64], r1 343 vaddw.u8 q15, q15, d7 344 vst1.64 {d4}, [r2,:64], r1 345 vqmovun.s16 d6, q14 346 vst1.64 {d5}, [r2,:64], r1 347 vqmovun.s16 d7, q15 348 vst1.64 {d6}, [r2,:64], r1 349 vst1.64 {d7}, [r2,:64], r1 350 bx lr 351endfunc 352 353function ff_vp3_idct_dc_add_neon, export=1 354 ldrsh r12, [r2] 355 mov r3, r0 356 add r12, r12, #15 357 vdup.16 q15, r12 358 mov r12, #0 359 strh r12, [r2] 360 vshr.s16 q15, q15, #5 361 362 vld1.8 {d0}, [r0,:64], r1 363 vld1.8 {d1}, [r0,:64], r1 364 vld1.8 {d2}, [r0,:64], r1 365 vaddw.u8 q8, q15, d0 366 vld1.8 {d3}, [r0,:64], r1 367 vaddw.u8 q9, q15, d1 368 vld1.8 {d4}, [r0,:64], r1 369 vaddw.u8 q10, q15, d2 370 vld1.8 {d5}, [r0,:64], r1 371 vaddw.u8 q11, q15, d3 372 vld1.8 {d6}, [r0,:64], r1 373 vaddw.u8 q12, q15, d4 374 vld1.8 {d7}, [r0,:64], r1 375 vaddw.u8 q13, q15, d5 376 vqmovun.s16 d0, q8 377 vaddw.u8 q14, q15, d6 378 vqmovun.s16 d1, q9 379 vaddw.u8 q15, q15, d7 380 vqmovun.s16 d2, q10 381 vst1.8 {d0}, [r3,:64], r1 382 vqmovun.s16 d3, q11 383 vst1.8 {d1}, [r3,:64], r1 384 vqmovun.s16 d4, q12 385 vst1.8 {d2}, [r3,:64], r1 386 vqmovun.s16 d5, q13 387 vst1.8 {d3}, [r3,:64], r1 388 vqmovun.s16 d6, q14 389 vst1.8 {d4}, [r3,:64], r1 390 vqmovun.s16 d7, q15 391 vst1.8 {d5}, [r3,:64], r1 392 vst1.8 {d6}, [r3,:64], r1 393 vst1.8 {d7}, [r3,:64], r1 394 bx lr 395endfunc 396