1/* 2 * DSP functions for Indeo Video Interactive codecs (Indeo4 and Indeo5) 3 * 4 * Copyright (c) 2009 Maxim Poliakovski 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/** 24 * @file 25 * DSP functions (inverse transforms, motion compensation, wavelet recompostions) 26 * for Indeo Video Interactive codecs. 27 */ 28 29#include "avcodec.h" 30#include "dsputil.h" 31#include "dwt.h" 32#include "ivi_common.h" 33#include "ivi_dsp.h" 34 35void ff_ivi_recompose53(const IVIPlaneDesc *plane, uint8_t *dst, 36 const int dst_pitch, const int num_bands) 37{ 38 int x, y, indx; 39 int32_t p0, p1, p2, p3, tmp0, tmp1, tmp2; 40 int32_t b0_1, b0_2, b1_1, b1_2, b1_3, b2_1, b2_2, b2_3, b2_4, b2_5, b2_6; 41 int32_t b3_1, b3_2, b3_3, b3_4, b3_5, b3_6, b3_7, b3_8, b3_9; 42 int32_t pitch, back_pitch; 43 const IDWTELEM *b0_ptr, *b1_ptr, *b2_ptr, *b3_ptr; 44 45 /* all bands should have the same pitch */ 46 pitch = plane->bands[0].pitch; 47 48 /* pixels at the position "y-1" will be set to pixels at the "y" for the 1st iteration */ 49 back_pitch = 0; 50 51 /* get pointers to the wavelet bands */ 52 b0_ptr = plane->bands[0].buf; 53 b1_ptr = plane->bands[1].buf; 54 b2_ptr = plane->bands[2].buf; 55 b3_ptr = plane->bands[3].buf; 56 57 for (y = 0; y < plane->height; y += 2) { 58 /* load storage variables with values */ 59 if (num_bands > 0) { 60 b0_1 = b0_ptr[0]; 61 b0_2 = b0_ptr[pitch]; 62 } 63 64 if (num_bands > 1) { 65 b1_1 = b1_ptr[back_pitch]; 66 b1_2 = b1_ptr[0]; 67 b1_3 = b1_1 - b1_2*6 + b1_ptr[pitch]; 68 } 69 70 if (num_bands > 2) { 71 b2_2 = b2_ptr[0]; // b2[x, y ] 72 b2_3 = b2_2; // b2[x+1,y ] = b2[x,y] 73 b2_5 = b2_ptr[pitch]; // b2[x ,y+1] 74 b2_6 = b2_5; // b2[x+1,y+1] = b2[x,y+1] 75 } 76 77 if (num_bands > 3) { 78 b3_2 = b3_ptr[back_pitch]; // b3[x ,y-1] 79 b3_3 = b3_2; // b3[x+1,y-1] = b3[x ,y-1] 80 b3_5 = b3_ptr[0]; // b3[x ,y ] 81 b3_6 = b3_5; // b3[x+1,y ] = b3[x ,y ] 82 b3_8 = b3_2 - b3_5*6 + b3_ptr[pitch]; 83 b3_9 = b3_8; 84 } 85 86 for (x = 0, indx = 0; x < plane->width; x+=2, indx++) { 87 /* some values calculated in the previous iterations can */ 88 /* be reused in the next ones, so do appropriate copying */ 89 b2_1 = b2_2; // b2[x-1,y ] = b2[x, y ] 90 b2_2 = b2_3; // b2[x ,y ] = b2[x+1,y ] 91 b2_4 = b2_5; // b2[x-1,y+1] = b2[x ,y+1] 92 b2_5 = b2_6; // b2[x ,y+1] = b2[x+1,y+1] 93 b3_1 = b3_2; // b3[x-1,y-1] = b3[x ,y-1] 94 b3_2 = b3_3; // b3[x ,y-1] = b3[x+1,y-1] 95 b3_4 = b3_5; // b3[x-1,y ] = b3[x ,y ] 96 b3_5 = b3_6; // b3[x ,y ] = b3[x+1,y ] 97 b3_7 = b3_8; // vert_HPF(x-1) 98 b3_8 = b3_9; // vert_HPF(x ) 99 100 p0 = p1 = p2 = p3 = 0; 101 102 /* process the LL-band by applying LPF both vertically and horizontally */ 103 if (num_bands > 0) { 104 tmp0 = b0_1; 105 tmp2 = b0_2; 106 b0_1 = b0_ptr[indx+1]; 107 b0_2 = b0_ptr[pitch+indx+1]; 108 tmp1 = tmp0 + b0_1; 109 110 p0 = tmp0 << 4; 111 p1 = tmp1 << 3; 112 p2 = (tmp0 + tmp2) << 3; 113 p3 = (tmp1 + tmp2 + b0_2) << 2; 114 } 115 116 /* process the HL-band by applying HPF vertically and LPF horizontally */ 117 if (num_bands > 1) { 118 tmp0 = b1_2; 119 tmp1 = b1_1; 120 b1_2 = b1_ptr[indx+1]; 121 b1_1 = b1_ptr[back_pitch+indx+1]; 122 123 tmp2 = tmp1 - tmp0*6 + b1_3; 124 b1_3 = b1_1 - b1_2*6 + b1_ptr[pitch+indx+1]; 125 126 p0 += (tmp0 + tmp1) << 3; 127 p1 += (tmp0 + tmp1 + b1_1 + b1_2) << 2; 128 p2 += tmp2 << 2; 129 p3 += (tmp2 + b1_3) << 1; 130 } 131 132 /* process the LH-band by applying LPF vertically and HPF horizontally */ 133 if (num_bands > 2) { 134 b2_3 = b2_ptr[indx+1]; 135 b2_6 = b2_ptr[pitch+indx+1]; 136 137 tmp0 = b2_1 + b2_2; 138 tmp1 = b2_1 - b2_2*6 + b2_3; 139 140 p0 += tmp0 << 3; 141 p1 += tmp1 << 2; 142 p2 += (tmp0 + b2_4 + b2_5) << 2; 143 p3 += (tmp1 + b2_4 - b2_5*6 + b2_6) << 1; 144 } 145 146 /* process the HH-band by applying HPF both vertically and horizontally */ 147 if (num_bands > 3) { 148 b3_6 = b3_ptr[indx+1]; // b3[x+1,y ] 149 b3_3 = b3_ptr[back_pitch+indx+1]; // b3[x+1,y-1] 150 151 tmp0 = b3_1 + b3_4; 152 tmp1 = b3_2 + b3_5; 153 tmp2 = b3_3 + b3_6; 154 155 b3_9 = b3_3 - b3_6*6 + b3_ptr[pitch+indx+1]; 156 157 p0 += (tmp0 + tmp1) << 2; 158 p1 += (tmp0 - tmp1*6 + tmp2) << 1; 159 p2 += (b3_7 + b3_8) << 1; 160 p3 += b3_7 - b3_8*6 + b3_9; 161 } 162 163 /* output four pixels */ 164 dst[x] = av_clip_uint8((p0 >> 6) + 128); 165 dst[x+1] = av_clip_uint8((p1 >> 6) + 128); 166 dst[dst_pitch+x] = av_clip_uint8((p2 >> 6) + 128); 167 dst[dst_pitch+x+1] = av_clip_uint8((p3 >> 6) + 128); 168 }// for x 169 170 dst += dst_pitch << 1; 171 172 back_pitch = -pitch; 173 174 b0_ptr += pitch; 175 b1_ptr += pitch; 176 b2_ptr += pitch; 177 b3_ptr += pitch; 178 } 179} 180 181/** butterfly operation for the inverse slant transform */ 182#define IVI_SLANT_BFLY(s1, s2, o1, o2, t) \ 183 t = s1 - s2;\ 184 o1 = s1 + s2;\ 185 o2 = t;\ 186 187/** This is a reflection a,b = 1/2, 5/4 for the inverse slant transform */ 188#define IVI_IREFLECT(s1, s2, o1, o2, t) \ 189 t = ((s1 + s2*2 + 2) >> 2) + s1;\ 190 o2 = ((s1*2 - s2 + 2) >> 2) - s2;\ 191 o1 = t;\ 192 193/** This is a reflection a,b = 1/2, 7/8 for the inverse slant transform */ 194#define IVI_SLANT_PART4(s1, s2, o1, o2, t) \ 195 t = s2 + ((s1*4 - s2 + 4) >> 3);\ 196 o2 = s1 + ((-s1 - s2*4 + 4) >> 3);\ 197 o1 = t;\ 198 199/** inverse slant8 transform */ 200#define IVI_INV_SLANT8(s1, s4, s8, s5, s2, s6, s3, s7,\ 201 d1, d2, d3, d4, d5, d6, d7, d8,\ 202 t0, t1, t2, t3, t4, t5, t6, t7, t8) {\ 203 IVI_SLANT_PART4(s4, s5, t4, t5, t0);\ 204\ 205 IVI_SLANT_BFLY(s1, t5, t1, t5, t0); IVI_SLANT_BFLY(s2, s6, t2, t6, t0);\ 206 IVI_SLANT_BFLY(s7, s3, t7, t3, t0); IVI_SLANT_BFLY(t4, s8, t4, t8, t0);\ 207\ 208 IVI_SLANT_BFLY(t1, t2, t1, t2, t0); IVI_IREFLECT (t4, t3, t4, t3, t0);\ 209 IVI_SLANT_BFLY(t5, t6, t5, t6, t0); IVI_IREFLECT (t8, t7, t8, t7, t0);\ 210 IVI_SLANT_BFLY(t1, t4, t1, t4, t0); IVI_SLANT_BFLY(t2, t3, t2, t3, t0);\ 211 IVI_SLANT_BFLY(t5, t8, t5, t8, t0); IVI_SLANT_BFLY(t6, t7, t6, t7, t0);\ 212 d1 = COMPENSATE(t1);\ 213 d2 = COMPENSATE(t2);\ 214 d3 = COMPENSATE(t3);\ 215 d4 = COMPENSATE(t4);\ 216 d5 = COMPENSATE(t5);\ 217 d6 = COMPENSATE(t6);\ 218 d7 = COMPENSATE(t7);\ 219 d8 = COMPENSATE(t8);} 220 221/** inverse slant4 transform */ 222#define IVI_INV_SLANT4(s1, s4, s2, s3, d1, d2, d3, d4, t0, t1, t2, t3, t4) {\ 223 IVI_SLANT_BFLY(s1, s2, t1, t2, t0); IVI_IREFLECT (s4, s3, t4, t3, t0);\ 224\ 225 IVI_SLANT_BFLY(t1, t4, t1, t4, t0); IVI_SLANT_BFLY(t2, t3, t2, t3, t0);\ 226 d1 = COMPENSATE(t1);\ 227 d2 = COMPENSATE(t2);\ 228 d3 = COMPENSATE(t3);\ 229 d4 = COMPENSATE(t4);} 230 231void ff_ivi_inverse_slant_8x8(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) 232{ 233 int i; 234 const int32_t *src; 235 int32_t *dst; 236 int tmp[64]; 237 int t0, t1, t2, t3, t4, t5, t6, t7, t8; 238 239#define COMPENSATE(x) (x) 240 src = in; 241 dst = tmp; 242 for (i = 0; i < 8; i++) { 243 if (flags[i]) { 244 IVI_INV_SLANT8(src[0], src[8], src[16], src[24], src[32], src[40], src[48], src[56], 245 dst[0], dst[8], dst[16], dst[24], dst[32], dst[40], dst[48], dst[56], 246 t0, t1, t2, t3, t4, t5, t6, t7, t8); 247 } else 248 dst[0] = dst[8] = dst[16] = dst[24] = dst[32] = dst[40] = dst[48] = dst[56] = 0; 249 250 src++; 251 dst++; 252 } 253#undef COMPENSATE 254 255#define COMPENSATE(x) ((x + 1)>>1) 256 src = tmp; 257 for (i = 0; i < 8; i++) { 258 if (!src[0] && !src[1] && !src[2] && !src[3] && !src[4] && !src[5] && !src[6] && !src[7]) { 259 memset(out, 0, 8*sizeof(out[0])); 260 } else { 261 IVI_INV_SLANT8(src[0], src[1], src[2], src[3], src[4], src[5], src[6], src[7], 262 out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], 263 t0, t1, t2, t3, t4, t5, t6, t7, t8); 264 } 265 src += 8; 266 out += pitch; 267 } 268#undef COMPENSATE 269} 270 271void ff_ivi_inverse_slant_4x4(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) 272{ 273 int i; 274 const int32_t *src; 275 int32_t *dst; 276 int tmp[16]; 277 int t0, t1, t2, t3, t4; 278 279#define COMPENSATE(x) (x) 280 src = in; 281 dst = tmp; 282 for (i = 0; i < 4; i++) { 283 if (flags[i]) { 284 IVI_INV_SLANT4(src[0], src[4], src[8], src[12], 285 dst[0], dst[4], dst[8], dst[12], 286 t0, t1, t2, t3, t4); 287 } else 288 dst[0] = dst[4] = dst[8] = dst[12] = 0; 289 290 src++; 291 dst++; 292 } 293#undef COMPENSATE 294 295#define COMPENSATE(x) ((x + 1)>>1) 296 src = tmp; 297 for (i = 0; i < 4; i++) { 298 if (!src[0] && !src[1] && !src[2] && !src[3]) { 299 out[0] = out[1] = out[2] = out[3] = 0; 300 } else { 301 IVI_INV_SLANT4(src[0], src[1], src[2], src[3], 302 out[0], out[1], out[2], out[3], 303 t0, t1, t2, t3, t4); 304 } 305 src += 4; 306 out += pitch; 307 } 308#undef COMPENSATE 309} 310 311void ff_ivi_dc_slant_2d(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size) 312{ 313 int x, y; 314 int16_t dc_coeff; 315 316 dc_coeff = (*in + 1) >> 1; 317 318 for (y = 0; y < blk_size; out += pitch, y++) { 319 for (x = 0; x < blk_size; x++) 320 out[x] = dc_coeff; 321 } 322} 323 324void ff_ivi_row_slant8(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) 325{ 326 int i; 327 int t0, t1, t2, t3, t4, t5, t6, t7, t8; 328 329#define COMPENSATE(x) ((x + 1)>>1) 330 for (i = 0; i < 8; i++) { 331 if (!in[0] && !in[1] && !in[2] && !in[3] && !in[4] && !in[5] && !in[6] && !in[7]) { 332 memset(out, 0, 8*sizeof(out[0])); 333 } else { 334 IVI_INV_SLANT8( in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7], 335 out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], 336 t0, t1, t2, t3, t4, t5, t6, t7, t8); 337 } 338 in += 8; 339 out += pitch; 340 } 341#undef COMPENSATE 342} 343 344void ff_ivi_dc_row_slant(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size) 345{ 346 int x, y; 347 int16_t dc_coeff; 348 349 dc_coeff = (*in + 1) >> 1; 350 351 for (x = 0; x < blk_size; x++) 352 out[x] = dc_coeff; 353 354 out += pitch; 355 356 for (y = 1; y < blk_size; out += pitch, y++) { 357 for (x = 0; x < blk_size; x++) 358 out[x] = 0; 359 } 360} 361 362void ff_ivi_col_slant8(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) 363{ 364 int i, row2, row4, row8; 365 int t0, t1, t2, t3, t4, t5, t6, t7, t8; 366 367 row2 = pitch << 1; 368 row4 = pitch << 2; 369 row8 = pitch << 3; 370 371#define COMPENSATE(x) ((x + 1)>>1) 372 for (i = 0; i < 8; i++) { 373 if (flags[i]) { 374 IVI_INV_SLANT8(in[0], in[8], in[16], in[24], in[32], in[40], in[48], in[56], 375 out[0], out[pitch], out[row2], out[row2 + pitch], out[row4], 376 out[row4 + pitch], out[row4 + row2], out[row8 - pitch], 377 t0, t1, t2, t3, t4, t5, t6, t7, t8); 378 } else { 379 out[0] = out[pitch] = out[row2] = out[row2 + pitch] = out[row4] = 380 out[row4 + pitch] = out[row4 + row2] = out[row8 - pitch] = 0; 381 } 382 383 in++; 384 out++; 385 } 386#undef COMPENSATE 387} 388 389void ff_ivi_dc_col_slant(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size) 390{ 391 int x, y; 392 int16_t dc_coeff; 393 394 dc_coeff = (*in + 1) >> 1; 395 396 for (y = 0; y < blk_size; out += pitch, y++) { 397 out[0] = dc_coeff; 398 for (x = 1; x < blk_size; x++) 399 out[x] = 0; 400 } 401} 402 403void ff_ivi_put_pixels_8x8(const int32_t *in, int16_t *out, uint32_t pitch, 404 const uint8_t *flags) 405{ 406 int x, y; 407 408 for (y = 0; y < 8; out += pitch, in += 8, y++) 409 for (x = 0; x < 8; x++) 410 out[x] = in[x]; 411} 412 413void ff_ivi_put_dc_pixel_8x8(const int32_t *in, int16_t *out, uint32_t pitch, 414 int blk_size) 415{ 416 int y; 417 418 out[0] = in[0]; 419 memset(out + 1, 0, 7*sizeof(out[0])); 420 out += pitch; 421 422 for (y = 1; y < 8; out += pitch, y++) 423 memset(out, 0, 8*sizeof(out[0])); 424} 425 426#define IVI_MC_TEMPLATE(size, suffix, OP) \ 427void ff_ivi_mc_ ## size ##x## size ## suffix (int16_t *buf, const int16_t *ref_buf, \ 428 uint32_t pitch, int mc_type) \ 429{ \ 430 int i, j; \ 431 const int16_t *wptr; \ 432\ 433 switch (mc_type) { \ 434 case 0: /* fullpel (no interpolation) */ \ 435 for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) { \ 436 for (j = 0; j < size; j++) {\ 437 OP(buf[j], ref_buf[j]); \ 438 } \ 439 } \ 440 break; \ 441 case 1: /* horizontal halfpel interpolation */ \ 442 for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) \ 443 for (j = 0; j < size; j++) \ 444 OP(buf[j], (ref_buf[j] + ref_buf[j+1]) >> 1); \ 445 break; \ 446 case 2: /* vertical halfpel interpolation */ \ 447 wptr = ref_buf + pitch; \ 448 for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \ 449 for (j = 0; j < size; j++) \ 450 OP(buf[j], (ref_buf[j] + wptr[j]) >> 1); \ 451 break; \ 452 case 3: /* vertical and horizontal halfpel interpolation */ \ 453 wptr = ref_buf + pitch; \ 454 for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \ 455 for (j = 0; j < size; j++) \ 456 OP(buf[j], (ref_buf[j] + ref_buf[j+1] + wptr[j] + wptr[j+1]) >> 2); \ 457 break; \ 458 } \ 459} \ 460 461#define OP_PUT(a, b) (a) = (b) 462#define OP_ADD(a, b) (a) += (b) 463 464IVI_MC_TEMPLATE(8, _no_delta, OP_PUT); 465IVI_MC_TEMPLATE(8, _delta, OP_ADD); 466IVI_MC_TEMPLATE(4, _no_delta, OP_PUT); 467IVI_MC_TEMPLATE(4, _delta, OP_ADD); 468