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*/ 100static 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*/ 337WORD32 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