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
CombinedHorzVertRingFilter(uint8 * rec,int width,int height,int16 * QP_store,int chr,uint8 * pp_mod)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