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 */
cac_4x8(UWORD8 * pu1_top,UWORD8 * pu1_bot,WORD32 top_strd,WORD32 bot_strd)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 */
ideint_cac_8x8(UWORD8 * pu1_top,UWORD8 * pu1_bot,WORD32 top_strd,WORD32 bot_strd)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