/src/libmpeg2/common/ideint_cac.c
Line | Count | Source |
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 | 7.24M | { |
105 | 7.24M | WORD32 ca; |
106 | 7.24M | WORD32 adj; |
107 | 7.24M | WORD32 alt; |
108 | 7.24M | UWORD8 *pu1_tmp_top; |
109 | 7.24M | UWORD8 *pu1_tmp_bot; |
110 | 7.24M | WORD32 i; |
111 | 7.24M | WORD32 j; |
112 | 7.24M | UWORD8 *pu1_top_0; |
113 | 7.24M | UWORD8 *pu1_top_1; |
114 | 7.24M | UWORD8 *pu1_top_2; |
115 | 7.24M | UWORD8 *pu1_top_3; |
116 | 7.24M | UWORD8 *pu1_bot_0; |
117 | 7.24M | UWORD8 *pu1_bot_1; |
118 | 7.24M | UWORD8 *pu1_bot_2; |
119 | 7.24M | UWORD8 *pu1_bot_3; |
120 | 7.24M | WORD32 rsum_csum_thresh; |
121 | 7.24M | WORD32 sad_bias_mult_shift; |
122 | 7.24M | WORD32 sad_bias_additive; |
123 | | |
124 | 7.24M | WORD32 diff_sum; |
125 | 7.24M | WORD32 top_row_end_incr; |
126 | 7.24M | WORD32 bot_row_end_incr; |
127 | | |
128 | 7.24M | ca = 0; |
129 | | |
130 | 7.24M | adj = 0; |
131 | 7.24M | alt = 0; |
132 | | |
133 | 7.24M | rsum_csum_thresh = RSUM_CSUM_THRESH; |
134 | 7.24M | sad_bias_additive = SAD_BIAS_ADDITIVE; |
135 | 7.24M | 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 | 7.24M | pu1_tmp_top = pu1_top; |
150 | 7.24M | pu1_tmp_bot = pu1_bot; |
151 | | |
152 | 7.24M | top_row_end_incr = top_strd - SUB_BLK_WD; |
153 | 7.24M | 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 | 21.3M | for(j = 0; j < BLK_HT; j += 4) |
160 | 14.1M | { |
161 | 14.1M | WORD32 sum_1, sum_2, sum_3, sum_4; |
162 | 14.1M | 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 | 14.1M | sum_1 = 0; |
169 | 14.1M | sum_2 = 0; |
170 | | |
171 | 70.7M | for(i = 0; i < SUB_BLK_WD; i ++) |
172 | 56.5M | { |
173 | 56.5M | sum_1 += *pu1_tmp_top++; |
174 | 56.5M | sum_2 += *pu1_tmp_bot++; |
175 | 56.5M | } |
176 | | |
177 | 14.1M | sum_diff = ABS_DIF(sum_1, sum_2); |
178 | | |
179 | | /*********************************************************************/ |
180 | | /* Thresholding. */ |
181 | | /*********************************************************************/ |
182 | 14.1M | if(sum_diff >= rsum_csum_thresh) |
183 | 167k | adj += sum_diff; |
184 | | |
185 | 14.1M | pu1_tmp_top += top_row_end_incr; |
186 | 14.1M | pu1_tmp_bot += bot_row_end_incr; |
187 | | |
188 | | |
189 | 14.1M | sum_3 = 0; |
190 | 14.1M | sum_4 = 0; |
191 | | |
192 | 70.6M | for(i = 0; i < SUB_BLK_WD; i ++) |
193 | 56.4M | { |
194 | 56.4M | sum_3 += *pu1_tmp_top++; |
195 | 56.4M | sum_4 += *pu1_tmp_bot++; |
196 | 56.4M | } |
197 | | |
198 | 14.1M | sum_diff = ABS_DIF(sum_3, sum_4); |
199 | | |
200 | | /*********************************************************************/ |
201 | | /* Thresholding. */ |
202 | | /*********************************************************************/ |
203 | 14.1M | if(sum_diff >= rsum_csum_thresh) |
204 | 166k | adj += sum_diff; |
205 | | |
206 | 14.1M | pu1_tmp_top += top_row_end_incr; |
207 | 14.1M | pu1_tmp_bot += bot_row_end_incr; |
208 | | |
209 | | /*************************************************************************/ |
210 | | /* Alt diff : Row based */ |
211 | | /*************************************************************************/ |
212 | 14.1M | alt += ABS_DIF(sum_1, sum_3); |
213 | 14.1M | alt += ABS_DIF(sum_2, sum_4); |
214 | | |
215 | 14.1M | } |
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 | 7.24M | pu1_top_0 = pu1_top; |
225 | 7.24M | pu1_top_1 = pu1_top_0 + top_strd; |
226 | 7.24M | pu1_top_2 = pu1_top_1 + top_strd; |
227 | 7.24M | pu1_top_3 = pu1_top_2 + top_strd; |
228 | | |
229 | 7.24M | pu1_bot_0 = pu1_bot; |
230 | 7.24M | pu1_bot_1 = pu1_bot_0 + bot_strd; |
231 | 7.24M | pu1_bot_2 = pu1_bot_1 + bot_strd; |
232 | 7.24M | pu1_bot_3 = pu1_bot_2 + bot_strd; |
233 | | |
234 | | /*************************************************************************/ |
235 | | /* Adj dif: Col based */ |
236 | | /*************************************************************************/ |
237 | 7.24M | 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 | 35.2M | for(i = 0; i < SUB_BLK_WD; i ++) |
245 | 28.0M | { |
246 | 28.0M | WORD32 val_1; |
247 | 28.0M | WORD32 val_2; |
248 | 28.0M | WORD32 tmp_1, tmp_2; |
249 | 28.0M | WORD32 tmp_diff; |
250 | | |
251 | 28.0M | tmp_1 = AVG(pu1_top_0[i], pu1_top_1[i]); |
252 | 28.0M | tmp_2 = AVG(pu1_top_2[i], pu1_top_3[i]); |
253 | 28.0M | val_1 = AVG(tmp_1, tmp_2); |
254 | | |
255 | 28.0M | tmp_1 = AVG(pu1_bot_0[i], pu1_bot_1[i]); |
256 | 28.0M | tmp_2 = AVG(pu1_bot_2[i], pu1_bot_3[i]); |
257 | 28.0M | val_2 = AVG(tmp_1, tmp_2); |
258 | | |
259 | 28.0M | tmp_diff = ABS_DIF(val_1, val_2); |
260 | | |
261 | 28.0M | if(tmp_diff >= (rsum_csum_thresh >> 2)) |
262 | 463k | diff_sum += tmp_diff; |
263 | 28.0M | } |
264 | | |
265 | | |
266 | 7.24M | adj += diff_sum << 2; |
267 | | |
268 | | /*************************************************************************/ |
269 | | /* Alt diff : Col based */ |
270 | | /*************************************************************************/ |
271 | 7.24M | diff_sum = 0; |
272 | | |
273 | 34.9M | for(i = 0; i < SUB_BLK_WD; i ++) |
274 | 27.7M | { |
275 | 27.7M | WORD32 val_1; |
276 | 27.7M | WORD32 val_2; |
277 | 27.7M | WORD32 tmp_1, tmp_2; |
278 | 27.7M | WORD32 tmp_diff; |
279 | | |
280 | 27.7M | tmp_1 = AVG(pu1_top_0[i], pu1_bot_0[i]); |
281 | 27.7M | tmp_2 = AVG(pu1_top_2[i], pu1_bot_2[i]); |
282 | 27.7M | val_1 = AVG(tmp_1, tmp_2); |
283 | | |
284 | 27.7M | tmp_1 = AVG(pu1_top_1[i], pu1_bot_1[i]); |
285 | 27.7M | tmp_2 = AVG(pu1_top_3[i], pu1_bot_3[i]); |
286 | 27.7M | val_2 = AVG(tmp_1, tmp_2); |
287 | | |
288 | 27.7M | tmp_diff = ABS_DIF(val_1, val_2); |
289 | | |
290 | 27.7M | diff_sum += tmp_diff; |
291 | 27.7M | } |
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 | 7.24M | alt += diff_sum << 2; |
299 | | |
300 | 7.24M | pu1_top += SUB_BLK_WD; |
301 | 7.24M | pu1_bot += SUB_BLK_WD; |
302 | | |
303 | 7.24M | alt += (alt >> sad_bias_mult_shift) + (sad_bias_additive >> 1); |
304 | 7.24M | ca = (alt < adj); |
305 | | |
306 | 7.24M | return ca; |
307 | 7.24M | } |
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 | 4.32M | { |
342 | 4.32M | WORD32 ca; /* combing artifact result */ |
343 | 4.32M | WORD32 k; |
344 | | |
345 | 4.32M | ca = 0; |
346 | | /*************************************************************************/ |
347 | | /* This loop runs for the two halves of the 4x8 block. */ |
348 | | /*************************************************************************/ |
349 | 11.4M | for(k = 0; k < 2; k ++) |
350 | 7.15M | { |
351 | 7.15M | ca |= cac_4x8(pu1_top, pu1_bot, top_strd, bot_strd); |
352 | | |
353 | 7.15M | pu1_top += SUB_BLK_WD; |
354 | 7.15M | pu1_bot += SUB_BLK_WD; |
355 | | |
356 | | /* If Combing Artifact is detected, then return. Else continue to |
357 | | * check the next half |
358 | | */ |
359 | 7.15M | if(ca) |
360 | 37.6k | return ca; |
361 | 7.15M | } |
362 | | |
363 | 4.29M | return ca; |
364 | 4.32M | } |
365 | | |