Home | History | Annotate | Download | only in src
      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