Home | History | Annotate | Download | only in common
      1 /******************************************************************************
      2  *
      3  * Copyright (C) 2015 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 /**
     21 *******************************************************************************
     22 * @file
     23 *  ideint_cac.c
     24 *
     25 * @brief
     26 *  This file include the definitions of the combing  artifact check function
     27 * of the de-interlacer and some  variant of that.
     28 *
     29 * @author
     30 *  Ittiam
     31 *
     32 * @par List of Functions:
     33 *  cac_4x8()
     34 *  ideint_cac()
     35 *
     36 * @remarks
     37 *  In the de-interlacer workspace, cac is not a seperate  assembly module as
     38 * it comes along with the  de_int_decision() function. But in C-Model, to
     39 * keep  the things cleaner, it was made to be a separate  function during
     40 * cac experiments long after the  assembly was written by Mudit.
     41 *
     42 *******************************************************************************
     43 */
     44 /*****************************************************************************/
     45 /* File Includes                                                             */
     46 /*****************************************************************************/
     47 /* System include files */
     48 #include <stdio.h>
     49 #include <stdint.h>
     50 #include <string.h>
     51 #include <stdlib.h>
     52 
     53 /* User include files */
     54 #include "icv_datatypes.h"
     55 #include "icv_macros.h"
     56 #include "icv.h"
     57 #include "icv_variance.h"
     58 #include "icv_sad.h"
     59 #include "ideint.h"
     60 #include "ideint_defs.h"
     61 #include "ideint_structs.h"
     62 #include "ideint_cac.h"
     63 
     64 /**
     65 *******************************************************************************
     66 *
     67 * @brief
     68 * Combing artifact check function for 8x4 block
     69 *
     70 * @par   Description
     71 *  Adjacent and alternate SADs are calculated by row based and column-based
     72 *  collapsing. The adjacent and alternate SADs are then compared with some
     73 *  biasing to get CAC
     74 *
     75 * @param[in] pu1_top
     76 *  Top field
     77 *
     78 * @param[in] pu1_bot
     79 *  Bottom field
     80 *
     81 * @param[in] top_strd
     82 *  Top field Stride
     83 *
     84 * @param[in] bot_strd
     85 *  Bottom field stride
     86 *
     87 * @param[in] pi4_adj_sad
     88 *  Pointer to return adjacent SAD
     89 *
     90 * @param[in] pi4_alt_sad
     91 *  Pointer to return alternate SAD
     92 *
     93 * @returns
     94 * combing artifact flag (1 = detected, 0 = not detected)
     95 *
     96 * @remarks
     97 *
     98 *******************************************************************************
     99 */
    100 static WORD32 cac_4x8(UWORD8 *pu1_top,
    101                       UWORD8 *pu1_bot,
    102                       WORD32 top_strd,
    103                       WORD32 bot_strd)
    104 {
    105     WORD32 ca;
    106     WORD32 adj;
    107     WORD32 alt;
    108     UWORD8 *pu1_tmp_top;
    109     UWORD8 *pu1_tmp_bot;
    110     WORD32 i;
    111     WORD32 j;
    112     UWORD8 *pu1_top_0;
    113     UWORD8 *pu1_top_1;
    114     UWORD8 *pu1_top_2;
    115     UWORD8 *pu1_top_3;
    116     UWORD8 *pu1_bot_0;
    117     UWORD8 *pu1_bot_1;
    118     UWORD8 *pu1_bot_2;
    119     UWORD8 *pu1_bot_3;
    120     WORD32 rsum_csum_thresh;
    121     WORD32 sad_bias_mult_shift;
    122     WORD32 sad_bias_additive;
    123 
    124     WORD32 diff_sum;
    125     WORD32 top_row_end_incr;
    126     WORD32 bot_row_end_incr;
    127 
    128     ca = 0;
    129 
    130     adj = 0;
    131     alt = 0;
    132 
    133     rsum_csum_thresh    = RSUM_CSUM_THRESH;
    134     sad_bias_additive   = SAD_BIAS_ADDITIVE;
    135     sad_bias_mult_shift = SAD_BIAS_MULT_SHIFT;
    136 
    137     /*************************************************************************/
    138     /* In the adjacent sad calculation by row-method, the absolute           */
    139     /* difference is taken between the adjacent rows. The pixels of the diff */
    140     /* row, thus obtained, are then summed up. If this sum of absolute       */
    141     /* differace (sad) is greater than a threshold value, it is added to the */
    142     /* adjcacent SAD value.                                                  */
    143     /*************************************************************************/
    144 
    145     /*************************************************************************/
    146     /* Adj dif: Row based                                                    */
    147     /*************************************************************************/
    148 
    149     pu1_tmp_top = pu1_top;
    150     pu1_tmp_bot = pu1_bot;
    151 
    152     top_row_end_incr = top_strd - SUB_BLK_WD;
    153     bot_row_end_incr = bot_strd - SUB_BLK_WD;
    154 
    155     /*************************************************************************/
    156     /* The outer-loop runs for BLK_HT/2 times, because one pixel   */
    157     /* is touched only once.                                                 */
    158     /*************************************************************************/
    159     for(j = 0; j < BLK_HT; j += 4)
    160     {
    161         WORD32 sum_1, sum_2, sum_3, sum_4;
    162         WORD32 sum_diff;
    163 
    164         /*********************************************************************/
    165         /* Because the 8x4 is split into two halves of 4x4, the width of the */
    166         /* block is now 4.                                                   */
    167         /*********************************************************************/
    168         sum_1 = 0;
    169         sum_2 = 0;
    170 
    171         for(i = 0; i < SUB_BLK_WD; i ++)
    172         {
    173             sum_1 += *pu1_tmp_top++;
    174             sum_2 += *pu1_tmp_bot++;
    175         }
    176 
    177         sum_diff = ABS_DIF(sum_1, sum_2);
    178 
    179         /*********************************************************************/
    180         /* Thresholding.                                                     */
    181         /*********************************************************************/
    182         if(sum_diff >= rsum_csum_thresh)
    183             adj += sum_diff;
    184 
    185         pu1_tmp_top += top_row_end_incr;
    186         pu1_tmp_bot += bot_row_end_incr;
    187 
    188 
    189         sum_3 = 0;
    190         sum_4 = 0;
    191 
    192         for(i = 0; i < SUB_BLK_WD; i ++)
    193         {
    194             sum_3 += *pu1_tmp_top++;
    195             sum_4 += *pu1_tmp_bot++;
    196         }
    197 
    198         sum_diff = ABS_DIF(sum_3, sum_4);
    199 
    200         /*********************************************************************/
    201         /* Thresholding.                                                     */
    202         /*********************************************************************/
    203         if(sum_diff >= rsum_csum_thresh)
    204             adj += sum_diff;
    205 
    206         pu1_tmp_top += top_row_end_incr;
    207         pu1_tmp_bot += bot_row_end_incr;
    208 
    209         /*************************************************************************/
    210         /* Alt diff : Row based                                                  */
    211         /*************************************************************************/
    212         alt += ABS_DIF(sum_1, sum_3);
    213         alt += ABS_DIF(sum_2, sum_4);
    214 
    215     }
    216 
    217     /*************************************************************************/
    218     /* In the adjacent sad calculation by column-method, the rows of both    */
    219     /* the fields are averaged separately and then summed across the column. */
    220     /* The difference of the two values, thus obtained, is added to the      */
    221     /* adjacent sad value, if it is beyond the threshold.                    */
    222     /*************************************************************************/
    223 
    224     pu1_top_0 = pu1_top;
    225     pu1_top_1 = pu1_top_0 + top_strd;
    226     pu1_top_2 = pu1_top_1 + top_strd;
    227     pu1_top_3 = pu1_top_2 + top_strd;
    228 
    229     pu1_bot_0 = pu1_bot;
    230     pu1_bot_1 = pu1_bot_0 + bot_strd;
    231     pu1_bot_2 = pu1_bot_1 + bot_strd;
    232     pu1_bot_3 = pu1_bot_2 + bot_strd;
    233 
    234     /*************************************************************************/
    235     /* Adj dif: Col based                                                    */
    236     /*************************************************************************/
    237     diff_sum = 0;
    238 
    239     /*************************************************************************/
    240     /* As the DSP implementation of this modules is anyway going to assume   */
    241     /* the size of the block to the fixed (8x4 or two 4x4's), the height of  */
    242     /* block is also kept to be 8, to have a clean implementation.           */
    243     /*************************************************************************/
    244     for(i = 0; i < SUB_BLK_WD; i ++)
    245     {
    246         WORD32 val_1;
    247         WORD32 val_2;
    248         WORD32 tmp_1, tmp_2;
    249         WORD32 tmp_diff;
    250 
    251         tmp_1 = AVG(pu1_top_0[i], pu1_top_1[i]);
    252         tmp_2 = AVG(pu1_top_2[i], pu1_top_3[i]);
    253         val_1 = AVG(tmp_1,        tmp_2);
    254 
    255         tmp_1 = AVG(pu1_bot_0[i], pu1_bot_1[i]);
    256         tmp_2 = AVG(pu1_bot_2[i], pu1_bot_3[i]);
    257         val_2 = AVG(tmp_1,        tmp_2);
    258 
    259         tmp_diff = ABS_DIF(val_1, val_2);
    260 
    261         if(tmp_diff >= (rsum_csum_thresh >> 2))
    262             diff_sum += tmp_diff;
    263     }
    264 
    265 
    266     adj += diff_sum << 2;
    267 
    268     /*************************************************************************/
    269     /* Alt diff : Col based                                                  */
    270     /*************************************************************************/
    271     diff_sum = 0;
    272 
    273     for(i = 0; i < SUB_BLK_WD; i ++)
    274     {
    275         WORD32 val_1;
    276         WORD32 val_2;
    277         WORD32 tmp_1, tmp_2;
    278         WORD32 tmp_diff;
    279 
    280         tmp_1 = AVG(pu1_top_0[i], pu1_bot_0[i]);
    281         tmp_2 = AVG(pu1_top_2[i], pu1_bot_2[i]);
    282         val_1 = AVG(tmp_1,        tmp_2);
    283 
    284         tmp_1 = AVG(pu1_top_1[i], pu1_bot_1[i]);
    285         tmp_2 = AVG(pu1_top_3[i], pu1_bot_3[i]);
    286         val_2 = AVG(tmp_1, tmp_2);
    287 
    288         tmp_diff = ABS_DIF(val_1, val_2);
    289 
    290         diff_sum += tmp_diff;
    291     }
    292 
    293     /*************************************************************************/
    294     /* because of the averaging used in place of summation, a factor of 4 is */
    295     /* needed while adding the the diff_sum to the sad.                      */
    296     /*************************************************************************/
    297 
    298     alt += diff_sum << 2;
    299 
    300     pu1_top += SUB_BLK_WD;
    301     pu1_bot += SUB_BLK_WD;
    302 
    303     alt += (alt >> sad_bias_mult_shift) + (sad_bias_additive >> 1);
    304     ca   = (alt < adj);
    305 
    306     return ca;
    307 }
    308 
    309 /**
    310 *******************************************************************************
    311 *
    312 * @brief
    313 * Combing artifact check function for 8x8 block
    314 *
    315 * @par   Description
    316 * Determines CAC for 8x8 block by calling 8x4 CAC function
    317 *
    318 * @param[in] pu1_top
    319 *  Top field
    320 *
    321 * @param[in] pu1_bot
    322 *  Bottom field
    323 *
    324 * @param[in] top_strd
    325 *  Top field Stride
    326 *
    327 * @param[in] bot_strd
    328 *  Bottom field stride
    329 *
    330 * @returns
    331 * combing artifact flag (1 = detected, 0 = not detected)
    332 *
    333 * @remarks
    334 *
    335 *******************************************************************************
    336 */
    337 WORD32 ideint_cac_8x8(UWORD8 *pu1_top,
    338                       UWORD8 *pu1_bot,
    339                       WORD32 top_strd,
    340                       WORD32 bot_strd)
    341 {
    342     WORD32 ca;        /* combing artifact result                          */
    343     WORD32 k;
    344 
    345     ca = 0;
    346     /*************************************************************************/
    347     /* This loop runs for the two halves of the 4x8 block.                   */
    348     /*************************************************************************/
    349     for(k = 0; k < 2; k ++)
    350     {
    351         ca |= cac_4x8(pu1_top, pu1_bot, top_strd, bot_strd);
    352 
    353         pu1_top += SUB_BLK_WD;
    354         pu1_bot += SUB_BLK_WD;
    355 
    356         /* If Combing Artifact is detected, then return. Else continue to
    357          * check the next half
    358          */
    359         if(ca)
    360             return ca;
    361     }
    362 
    363     return ca;
    364 }
    365 
    366