1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 #include "mp4dec_lib.h" 19 #include "post_proc.h" 20 21 #ifdef PV_POSTPROC_ON 22 23 void CombinedHorzVertRingFilter( 24 uint8 *rec, 25 int width, 26 int height, 27 int16 *QP_store, 28 int chr, 29 uint8 *pp_mod) 30 { 31 32 /*---------------------------------------------------------------------------- 33 ; Define all local variables 34 ----------------------------------------------------------------------------*/ 35 int index, counter; 36 int br, bc, incr, mbr, mbc; 37 int QP = 1; 38 int v[5]; 39 uint8 *ptr, *ptr_c, *ptr_n; 40 int w1, w2, w3, w4; 41 int pp_w, pp_h, brwidth; 42 int sum, delta; 43 int a3_0, a3_1, a3_2, A3_0; 44 /* for Deringing Threshold approach (MPEG4)*/ 45 int max_diff, thres, v0, h0, min_blk, max_blk; 46 int cnthflag; 47 48 /*---------------------------------------------------------------------------- 49 ; Function body here 50 ----------------------------------------------------------------------------*/ 51 /* Calculate the width and height of the area in blocks (divide by 8) */ 52 pp_w = (width >> 3); 53 pp_h = (height >> 3); 54 55 /* Set up various values needed for updating pointers into rec */ 56 w1 = width; /* Offset to next row in pixels */ 57 w2 = width << 1; /* Offset to two rows in pixels */ 58 w3 = w1 + w2; /* Offset to three rows in pixels */ 59 w4 = w2 << 1; /* Offset to four rows in pixels */ 60 incr = width - BLKSIZE; /* Offset to next row after processing block */ 61 62 /* Work through the area hortizontally by two rows per step */ 63 for (mbr = 0; mbr < pp_h; mbr += 2) 64 { 65 /* brwidth contains the block number of the leftmost block 66 * of the current row */ 67 brwidth = mbr * pp_w; 68 69 /* Work through the area vertically by two columns per step */ 70 for (mbc = 0; mbc < pp_w; mbc += 2) 71 { 72 /* if the data is luminance info, get the correct 73 * quantization paramenter. One parameter per macroblock */ 74 if (!chr) 75 { 76 /* brwidth/4 is the macroblock number and mbc/2 is the macroblock col number*/ 77 QP = QP_store[(brwidth>>2) + (mbc>>1)]; 78 } 79 80 /****************** Horiz. Filtering ********************/ 81 /* Process four blocks for the filtering */ 82 /********************************************************/ 83 /* Loop over two rows of blocks */ 84 for (br = mbr + 1; br < mbr + 3; br++) /* br is the row counter in blocks */ 85 { 86 /* Set brwidth to the first (leftmost) block number of the next row */ 87 /* brwidth is used as an index when counting blocks */ 88 brwidth += pp_w; 89 90 /* Loop over two columns of blocks in the row */ 91 for (bc = mbc; bc < mbc + 2; bc++) /* bc is the column counter in blocks */ 92 { 93 /****** check boundary for deblocking ************/ 94 /* Execute if the row and column counters are within the area */ 95 if (br < pp_h && bc < pp_w) 96 { 97 /* Set the ptr to the first pixel of the first block of the second row 98 * brwidth * 64 is the pixel row offset 99 * bc * 8 is the pixel column offset */ 100 ptr = rec + (brwidth << 6) + (bc << 3); 101 102 /* Set the index to the current block of the second row counting in blocks */ 103 index = brwidth + bc; 104 105 /* if the data is chrominance info, get the correct 106 * quantization paramenter. One parameter per block. */ 107 if (chr) 108 { 109 QP = QP_store[index]; 110 } 111 112 /* Execute hard horizontal filter if semaphore for horizontal deblocking 113 * is set for the current block and block immediately above it */ 114 if (((pp_mod[index]&0x02) != 0) && ((pp_mod[index-pp_w]&0x02) != 0)) 115 { /* Hard filter */ 116 117 /* Set HorzHflag (bit 4) in the pp_mod location */ 118 pp_mod[index-pp_w] |= 0x10; /* 4/26/00 reuse pp_mod for HorzHflag*/ 119 120 /* Filter across the 8 pixels of the block */ 121 for (index = BLKSIZE; index > 0; index--) 122 { 123 /* Difference between the current pixel and the pixel above it */ 124 a3_0 = *ptr - *(ptr - w1); 125 126 /* if the magnitude of the difference is greater than the KThH threshold 127 * and within the quantization parameter, apply hard filter */ 128 if ((a3_0 > KThH || a3_0 < -KThH) && a3_0<QP && a3_0> -QP) 129 { 130 ptr_c = ptr - w3; /* Points to pixel three rows above */ 131 ptr_n = ptr + w1; /* Points to pixel one row below */ 132 v[0] = (int)(*(ptr_c - w3)); 133 v[1] = (int)(*(ptr_c - w2)); 134 v[2] = (int)(*(ptr_c - w1)); 135 v[3] = (int)(*ptr_c); 136 v[4] = (int)(*(ptr_c + w1)); 137 138 sum = v[0] 139 + v[1] 140 + v[2] 141 + *ptr_c 142 + v[4] 143 + (*(ptr_c + w2)) 144 + (*(ptr_c + w3)); /* Current pixel */ 145 146 delta = (sum + *ptr_c + 4) >> 3; /* Average pixel values with rounding */ 147 *(ptr_c) = (uint8) delta; 148 149 /* Move pointer down one row of pixels (points to pixel two rows 150 * above current pixel) */ 151 ptr_c += w1; 152 153 for (counter = 0; counter < 5; counter++) 154 { 155 /* Subtract off highest pixel and add in pixel below */ 156 sum = sum - v[counter] + *ptr_n; 157 /* Average the pixel values with rounding */ 158 delta = (sum + *ptr_c + 4) >> 3; 159 *ptr_c = (uint8)(delta); 160 161 /* Increment pointers to next pixel row */ 162 ptr_c += w1; 163 ptr_n += w1; 164 } 165 } 166 /* Increment pointer to next pixel */ 167 ++ptr; 168 } /* index*/ 169 } 170 else 171 { /* soft filter*/ 172 173 /* Clear HorzHflag (bit 4) in the pp_mod location */ 174 pp_mod[index-pp_w] &= 0xef; /* reset 1110,1111 */ 175 176 for (index = BLKSIZE; index > 0; index--) 177 { 178 /* Difference between the current pixel and the pixel above it */ 179 a3_0 = *(ptr) - *(ptr - w1); 180 181 /* if the magnitude of the difference is greater than the KTh threshold, 182 * apply soft filter */ 183 if ((a3_0 > KTh || a3_0 < -KTh)) 184 { 185 186 /* Sum of weighted differences */ 187 a3_0 += ((*(ptr - w2) - *(ptr + w1)) << 1) + (a3_0 << 2); 188 189 /* Check if sum is less than the quantization parameter */ 190 if (PV_ABS(a3_0) < (QP << 3)) 191 { 192 a3_1 = *(ptr - w2) - *(ptr - w3); 193 a3_1 += ((*(ptr - w4) - *(ptr - w1)) << 1) + (a3_1 << 2); 194 195 a3_2 = *(ptr + w2) - *(ptr + w1); 196 a3_2 += ((*(ptr) - *(ptr + w3)) << 1) + (a3_2 << 2); 197 198 A3_0 = PV_ABS(a3_0) - PV_MIN(PV_ABS(a3_1), PV_ABS(a3_2)); 199 200 if (A3_0 > 0) 201 { 202 A3_0 += A3_0 << 2; 203 A3_0 = (A3_0 + 32) >> 6; 204 if (a3_0 > 0) 205 { 206 A3_0 = -A3_0; 207 } 208 209 delta = (*(ptr - w1) - *(ptr)) >> 1; 210 if (delta >= 0) 211 { 212 if (delta >= A3_0) 213 { 214 delta = PV_MAX(A3_0, 0); 215 } 216 } 217 else 218 { 219 if (A3_0 > 0) 220 { 221 delta = 0; 222 } 223 else 224 { 225 delta = PV_MAX(A3_0, delta); 226 } 227 } 228 229 *(ptr - w1) = (uint8)(*(ptr - w1) - delta); 230 *(ptr) = (uint8)(*(ptr) + delta); 231 } 232 } /*threshold*/ 233 } 234 /* Increment pointer to next pixel */ 235 ++ptr; 236 } /*index*/ 237 } /* Soft filter*/ 238 }/* boundary checking*/ 239 }/*bc*/ 240 }/*br*/ 241 brwidth -= (pp_w << 1); 242 243 244 /****************** Vert. Filtering *********************/ 245 /* Process four blocks for the filtering */ 246 /********************************************************/ 247 /* Loop over two rows of blocks */ 248 for (br = mbr; br < mbr + 2; br++) /* br is the row counter in blocks */ 249 { 250 for (bc = mbc + 1; bc < mbc + 3; bc++) /* bc is the column counter in blocks */ 251 { 252 /****** check boundary for deblocking ************/ 253 /* Execute if the row and column counters are within the area */ 254 if (br < pp_h && bc < pp_w) 255 { 256 /* Set the ptr to the first pixel of the first block of the second row 257 * brwidth * 64 is the pixel row offset 258 * bc * 8 is the pixel column offset */ 259 ptr = rec + (brwidth << 6) + (bc << 3); 260 261 /* Set the index to the current block of the second row counting in blocks */ 262 index = brwidth + bc; 263 264 /* if the data is chrominance info, get the correct 265 * quantization paramenter. One parameter per block. */ 266 if (chr) 267 { 268 QP = QP_store[index]; 269 } 270 271 /* Execute hard vertical filter if semaphore for vertical deblocking 272 * is set for the current block and block immediately left of it */ 273 if (((pp_mod[index-1]&0x01) != 0) && ((pp_mod[index]&0x01) != 0)) 274 { /* Hard filter */ 275 276 /* Set VertHflag (bit 5) in the pp_mod location of previous block*/ 277 pp_mod[index-1] |= 0x20; /* 4/26/00 reuse pp_mod for VertHflag*/ 278 279 /* Filter across the 8 pixels of the block */ 280 for (index = BLKSIZE; index > 0; index--) 281 { 282 /* Difference between the current pixel 283 * and the pixel to left of it */ 284 a3_0 = *ptr - *(ptr - 1); 285 286 /* if the magnitude of the difference is greater than the KThH threshold 287 * and within the quantization parameter, apply hard filter */ 288 if ((a3_0 > KThH || a3_0 < -KThH) && a3_0<QP && a3_0> -QP) 289 { 290 ptr_c = ptr - 3; 291 ptr_n = ptr + 1; 292 v[0] = (int)(*(ptr_c - 3)); 293 v[1] = (int)(*(ptr_c - 2)); 294 v[2] = (int)(*(ptr_c - 1)); 295 v[3] = (int)(*ptr_c); 296 v[4] = (int)(*(ptr_c + 1)); 297 298 sum = v[0] 299 + v[1] 300 + v[2] 301 + *ptr_c 302 + v[4] 303 + (*(ptr_c + 2)) 304 + (*(ptr_c + 3)); 305 306 delta = (sum + *ptr_c + 4) >> 3; 307 *(ptr_c) = (uint8) delta; 308 309 /* Move pointer down one pixel to the right */ 310 ptr_c += 1; 311 for (counter = 0; counter < 5; counter++) 312 { 313 /* Subtract off highest pixel and add in pixel below */ 314 sum = sum - v[counter] + *ptr_n; 315 /* Average the pixel values with rounding */ 316 delta = (sum + *ptr_c + 4) >> 3; 317 *ptr_c = (uint8)(delta); 318 319 /* Increment pointers to next pixel */ 320 ptr_c += 1; 321 ptr_n += 1; 322 } 323 } 324 /* Increment pointers to next pixel row */ 325 ptr += w1; 326 } /* index*/ 327 } 328 else 329 { /* soft filter*/ 330 331 /* Clear VertHflag (bit 5) in the pp_mod location */ 332 pp_mod[index-1] &= 0xdf; /* reset 1101,1111 */ 333 for (index = BLKSIZE; index > 0; index--) 334 { 335 /* Difference between the current pixel and the pixel above it */ 336 a3_0 = *(ptr) - *(ptr - 1); 337 338 /* if the magnitude of the difference is greater than the KTh threshold, 339 * apply soft filter */ 340 if ((a3_0 > KTh || a3_0 < -KTh)) 341 { 342 343 /* Sum of weighted differences */ 344 a3_0 += ((*(ptr - 2) - *(ptr + 1)) << 1) + (a3_0 << 2); 345 346 /* Check if sum is less than the quantization parameter */ 347 if (PV_ABS(a3_0) < (QP << 3)) 348 { 349 a3_1 = *(ptr - 2) - *(ptr - 3); 350 a3_1 += ((*(ptr - 4) - *(ptr - 1)) << 1) + (a3_1 << 2); 351 352 a3_2 = *(ptr + 2) - *(ptr + 1); 353 a3_2 += ((*(ptr) - *(ptr + 3)) << 1) + (a3_2 << 2); 354 355 A3_0 = PV_ABS(a3_0) - PV_MIN(PV_ABS(a3_1), PV_ABS(a3_2)); 356 357 if (A3_0 > 0) 358 { 359 A3_0 += A3_0 << 2; 360 A3_0 = (A3_0 + 32) >> 6; 361 if (a3_0 > 0) 362 { 363 A3_0 = -A3_0; 364 } 365 366 delta = (*(ptr - 1) - *(ptr)) >> 1; 367 if (delta >= 0) 368 { 369 if (delta >= A3_0) 370 { 371 delta = PV_MAX(A3_0, 0); 372 } 373 } 374 else 375 { 376 if (A3_0 > 0) 377 { 378 delta = 0; 379 } 380 else 381 { 382 delta = PV_MAX(A3_0, delta); 383 } 384 } 385 386 *(ptr - 1) = (uint8)(*(ptr - 1) - delta); 387 *(ptr) = (uint8)(*(ptr) + delta); 388 } 389 } /*threshold*/ 390 } 391 ptr += w1; 392 } /*index*/ 393 } /* Soft filter*/ 394 } /* boundary*/ 395 } /*bc*/ 396 /* Increment pointer to next row of pixels */ 397 brwidth += pp_w; 398 }/*br*/ 399 brwidth -= (pp_w << 1); 400 401 /****************** Deringing ***************************/ 402 /* Process four blocks for the filtering */ 403 /********************************************************/ 404 /* Loop over two rows of blocks */ 405 for (br = mbr; br < mbr + 2; br++) 406 { 407 /* Loop over two columns of blocks in the row */ 408 for (bc = mbc; bc < mbc + 2; bc++) 409 { 410 /* Execute if the row and column counters are within the area */ 411 if (br < pp_h && bc < pp_w) 412 { 413 /* Set the index to the current block */ 414 index = brwidth + bc; 415 416 /* Execute deringing if semaphore for deringing (bit-3 of pp_mod) 417 * is set for the current block */ 418 if ((pp_mod[index]&0x04) != 0) 419 { 420 /* Don't process deringing if on an edge block */ 421 if (br > 0 && bc > 0 && br < pp_h - 1 && bc < pp_w - 1) 422 { 423 /* cnthflag = weighted average of HorzHflag of current, 424 * one above, previous blocks*/ 425 cnthflag = ((pp_mod[index] & 0x10) + 426 (pp_mod[index-pp_w] & 0x10) + 427 ((pp_mod[index-1] >> 1) & 0x10) + 428 ((pp_mod[index] >> 1) & 0x10)) >> 4; /* 4/26/00*/ 429 430 /* Do the deringing if decision flags indicate it's necessary */ 431 if (cnthflag < 3) 432 { 433 /* if the data is chrominance info, get the correct 434 * quantization paramenter. One parameter per block. */ 435 if (chr) 436 { 437 QP = QP_store[index]; 438 } 439 440 /* Set amount to change luminance if it needs to be changed 441 * based on quantization parameter */ 442 max_diff = (QP >> 2) + 4; 443 444 /* Set pointer to first pixel of current block */ 445 ptr = rec + (brwidth << 6) + (bc << 3); 446 447 /* Find minimum and maximum value of pixel block */ 448 FindMaxMin(ptr, &min_blk, &max_blk, incr); 449 450 /* threshold determination */ 451 thres = (max_blk + min_blk + 1) >> 1; 452 453 /* If pixel range is greater or equal than DERING_THR, smooth the region */ 454 if ((max_blk - min_blk) >= DERING_THR) /*smooth 8x8 region*/ 455 #ifndef NoMMX 456 { 457 /* smooth all pixels in the block*/ 458 DeringAdaptiveSmoothMMX(ptr, width, thres, max_diff); 459 } 460 #else 461 { 462 /* Setup the starting point of the region to smooth */ 463 v0 = (br << 3) - 1; 464 h0 = (bc << 3) - 1; 465 466 /*smooth 8x8 region*/ 467 AdaptiveSmooth_NoMMX(rec, v0, h0, v0 + 1, h0 + 1, thres, width, max_diff); 468 } 469 #endif 470 }/*cnthflag*/ 471 } /*dering br==1 or bc==1 (boundary block)*/ 472 else /* Process the boundary blocks */ 473 { 474 /* Decide to perform deblocking based on the semaphore flags 475 * of the neighboring blocks in each case. A certain number of 476 * hard filtering flags have to be set in order to signal need 477 * for smoothing */ 478 if (br > 0 && br < pp_h - 1) 479 { 480 if (bc > 0) 481 { 482 cnthflag = ((pp_mod[index-pp_w] & 0x10) + 483 (pp_mod[index] & 0x10) + 484 ((pp_mod[index-1] >> 1) & 0x10)) >> 4; 485 } 486 else 487 { 488 cnthflag = ((pp_mod[index] & 0x10) + 489 (pp_mod[index-pp_w] & 0x10) + 490 ((pp_mod[index] >> 1) & 0x10)) >> 4; 491 } 492 } 493 else if (bc > 0 && bc < pp_w - 1) 494 { 495 if (br > 0) 496 { 497 cnthflag = ((pp_mod[index-pp_w] & 0x10) + 498 ((pp_mod[index-1] >> 1) & 0x10) + 499 ((pp_mod[index] >> 1) & 0x10)) >> 4; 500 } 501 else 502 { 503 cnthflag = ((pp_mod[index] & 0x10) + 504 ((pp_mod[index-1] >> 1) & 0x10) + 505 ((pp_mod[index] >> 1) & 0x10)) >> 4; 506 } 507 } 508 else /* at the corner do default*/ 509 { 510 cnthflag = 0; 511 } 512 513 /* Do the deringing if decision flags indicate it's necessary */ 514 if (cnthflag < 2) 515 { 516 517 /* if the data is chrominance info, get the correct 518 * quantization paramenter. One parameter per block. */ 519 if (chr) 520 { 521 QP = QP_store[index]; 522 } 523 524 /* Set amount to change luminance if it needs to be changed 525 * based on quantization parameter */ 526 max_diff = (QP >> 2) + 4; 527 528 /* Set pointer to first pixel of current block */ 529 ptr = rec + (brwidth << 6) + (bc << 3); 530 531 /* Find minimum and maximum value of pixel block */ 532 FindMaxMin(ptr, &min_blk, &max_blk, incr); 533 534 /* threshold determination */ 535 thres = (max_blk + min_blk + 1) >> 1; 536 537 /* Setup the starting point of the region to smooth 538 * This is going to be a 4x4 region */ 539 v0 = (br << 3) + 1; 540 h0 = (bc << 3) + 1; 541 542 /* If pixel range is greater or equal than DERING_THR, smooth the region */ 543 if ((max_blk - min_blk) >= DERING_THR) 544 { 545 /* Smooth 4x4 region */ 546 AdaptiveSmooth_NoMMX(rec, v0, h0, v0 - 3, h0 - 3, thres, width, max_diff); 547 } 548 }/*cnthflag*/ 549 } /* br==0, bc==0*/ 550 } /* dering*/ 551 } /*boundary condition*/ 552 }/*bc*/ 553 brwidth += pp_w; 554 }/*br*/ 555 brwidth -= (pp_w << 1); 556 }/*mbc*/ 557 brwidth += (pp_w << 1); 558 }/*mbr*/ 559 560 /*---------------------------------------------------------------------------- 561 ; Return nothing or data or data pointer 562 ----------------------------------------------------------------------------*/ 563 return ; 564 } 565 #endif 566