chvr_filter.cpp revision 3306cfee3bf38ab207a0504e49c2d492bb73ffbf
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
23void 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