summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp')
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp565
1 files changed, 565 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp
new file mode 100644
index 0000000..795cf71
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp
@@ -0,0 +1,565 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4dec_lib.h"
+#include "post_proc.h"
+
+#ifdef PV_POSTPROC_ON
+
+void CombinedHorzVertRingFilter(
+ uint8 *rec,
+ int width,
+ int height,
+ int16 *QP_store,
+ int chr,
+ uint8 *pp_mod)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int index, counter;
+ int br, bc, incr, mbr, mbc;
+ int QP = 1;
+ int v[5];
+ uint8 *ptr, *ptr_c, *ptr_n;
+ int w1, w2, w3, w4;
+ int pp_w, pp_h, brwidth;
+ int sum, delta;
+ int a3_0, a3_1, a3_2, A3_0;
+ /* for Deringing Threshold approach (MPEG4)*/
+ int max_diff, thres, v0, h0, min_blk, max_blk;
+ int cnthflag;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Calculate the width and height of the area in blocks (divide by 8) */
+ pp_w = (width >> 3);
+ pp_h = (height >> 3);
+
+ /* Set up various values needed for updating pointers into rec */
+ w1 = width; /* Offset to next row in pixels */
+ w2 = width << 1; /* Offset to two rows in pixels */
+ w3 = w1 + w2; /* Offset to three rows in pixels */
+ w4 = w2 << 1; /* Offset to four rows in pixels */
+ incr = width - BLKSIZE; /* Offset to next row after processing block */
+
+ /* Work through the area hortizontally by two rows per step */
+ for (mbr = 0; mbr < pp_h; mbr += 2)
+ {
+ /* brwidth contains the block number of the leftmost block
+ * of the current row */
+ brwidth = mbr * pp_w;
+
+ /* Work through the area vertically by two columns per step */
+ for (mbc = 0; mbc < pp_w; mbc += 2)
+ {
+ /* if the data is luminance info, get the correct
+ * quantization paramenter. One parameter per macroblock */
+ if (!chr)
+ {
+ /* brwidth/4 is the macroblock number and mbc/2 is the macroblock col number*/
+ QP = QP_store[(brwidth>>2) + (mbc>>1)];
+ }
+
+ /****************** Horiz. Filtering ********************/
+ /* Process four blocks for the filtering */
+ /********************************************************/
+ /* Loop over two rows of blocks */
+ for (br = mbr + 1; br < mbr + 3; br++) /* br is the row counter in blocks */
+ {
+ /* Set brwidth to the first (leftmost) block number of the next row */
+ /* brwidth is used as an index when counting blocks */
+ brwidth += pp_w;
+
+ /* Loop over two columns of blocks in the row */
+ for (bc = mbc; bc < mbc + 2; bc++) /* bc is the column counter in blocks */
+ {
+ /****** check boundary for deblocking ************/
+ /* Execute if the row and column counters are within the area */
+ if (br < pp_h && bc < pp_w)
+ {
+ /* Set the ptr to the first pixel of the first block of the second row
+ * brwidth * 64 is the pixel row offset
+ * bc * 8 is the pixel column offset */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Set the index to the current block of the second row counting in blocks */
+ index = brwidth + bc;
+
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Execute hard horizontal filter if semaphore for horizontal deblocking
+ * is set for the current block and block immediately above it */
+ if (((pp_mod[index]&0x02) != 0) && ((pp_mod[index-pp_w]&0x02) != 0))
+ { /* Hard filter */
+
+ /* Set HorzHflag (bit 4) in the pp_mod location */
+ pp_mod[index-pp_w] |= 0x10; /* 4/26/00 reuse pp_mod for HorzHflag*/
+
+ /* Filter across the 8 pixels of the block */
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel and the pixel above it */
+ a3_0 = *ptr - *(ptr - w1);
+
+ /* if the magnitude of the difference is greater than the KThH threshold
+ * and within the quantization parameter, apply hard filter */
+ if ((a3_0 > KThH || a3_0 < -KThH) && a3_0<QP && a3_0> -QP)
+ {
+ ptr_c = ptr - w3; /* Points to pixel three rows above */
+ ptr_n = ptr + w1; /* Points to pixel one row below */
+ v[0] = (int)(*(ptr_c - w3));
+ v[1] = (int)(*(ptr_c - w2));
+ v[2] = (int)(*(ptr_c - w1));
+ v[3] = (int)(*ptr_c);
+ v[4] = (int)(*(ptr_c + w1));
+
+ sum = v[0]
+ + v[1]
+ + v[2]
+ + *ptr_c
+ + v[4]
+ + (*(ptr_c + w2))
+ + (*(ptr_c + w3)); /* Current pixel */
+
+ delta = (sum + *ptr_c + 4) >> 3; /* Average pixel values with rounding */
+ *(ptr_c) = (uint8) delta;
+
+ /* Move pointer down one row of pixels (points to pixel two rows
+ * above current pixel) */
+ ptr_c += w1;
+
+ for (counter = 0; counter < 5; counter++)
+ {
+ /* Subtract off highest pixel and add in pixel below */
+ sum = sum - v[counter] + *ptr_n;
+ /* Average the pixel values with rounding */
+ delta = (sum + *ptr_c + 4) >> 3;
+ *ptr_c = (uint8)(delta);
+
+ /* Increment pointers to next pixel row */
+ ptr_c += w1;
+ ptr_n += w1;
+ }
+ }
+ /* Increment pointer to next pixel */
+ ++ptr;
+ } /* index*/
+ }
+ else
+ { /* soft filter*/
+
+ /* Clear HorzHflag (bit 4) in the pp_mod location */
+ pp_mod[index-pp_w] &= 0xef; /* reset 1110,1111 */
+
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel and the pixel above it */
+ a3_0 = *(ptr) - *(ptr - w1);
+
+ /* if the magnitude of the difference is greater than the KTh threshold,
+ * apply soft filter */
+ if ((a3_0 > KTh || a3_0 < -KTh))
+ {
+
+ /* Sum of weighted differences */
+ a3_0 += ((*(ptr - w2) - *(ptr + w1)) << 1) + (a3_0 << 2);
+
+ /* Check if sum is less than the quantization parameter */
+ if (PV_ABS(a3_0) < (QP << 3))
+ {
+ a3_1 = *(ptr - w2) - *(ptr - w3);
+ a3_1 += ((*(ptr - w4) - *(ptr - w1)) << 1) + (a3_1 << 2);
+
+ a3_2 = *(ptr + w2) - *(ptr + w1);
+ a3_2 += ((*(ptr) - *(ptr + w3)) << 1) + (a3_2 << 2);
+
+ A3_0 = PV_ABS(a3_0) - PV_MIN(PV_ABS(a3_1), PV_ABS(a3_2));
+
+ if (A3_0 > 0)
+ {
+ A3_0 += A3_0 << 2;
+ A3_0 = (A3_0 + 32) >> 6;
+ if (a3_0 > 0)
+ {
+ A3_0 = -A3_0;
+ }
+
+ delta = (*(ptr - w1) - *(ptr)) >> 1;
+ if (delta >= 0)
+ {
+ if (delta >= A3_0)
+ {
+ delta = PV_MAX(A3_0, 0);
+ }
+ }
+ else
+ {
+ if (A3_0 > 0)
+ {
+ delta = 0;
+ }
+ else
+ {
+ delta = PV_MAX(A3_0, delta);
+ }
+ }
+
+ *(ptr - w1) = (uint8)(*(ptr - w1) - delta);
+ *(ptr) = (uint8)(*(ptr) + delta);
+ }
+ } /*threshold*/
+ }
+ /* Increment pointer to next pixel */
+ ++ptr;
+ } /*index*/
+ } /* Soft filter*/
+ }/* boundary checking*/
+ }/*bc*/
+ }/*br*/
+ brwidth -= (pp_w << 1);
+
+
+ /****************** Vert. Filtering *********************/
+ /* Process four blocks for the filtering */
+ /********************************************************/
+ /* Loop over two rows of blocks */
+ for (br = mbr; br < mbr + 2; br++) /* br is the row counter in blocks */
+ {
+ for (bc = mbc + 1; bc < mbc + 3; bc++) /* bc is the column counter in blocks */
+ {
+ /****** check boundary for deblocking ************/
+ /* Execute if the row and column counters are within the area */
+ if (br < pp_h && bc < pp_w)
+ {
+ /* Set the ptr to the first pixel of the first block of the second row
+ * brwidth * 64 is the pixel row offset
+ * bc * 8 is the pixel column offset */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Set the index to the current block of the second row counting in blocks */
+ index = brwidth + bc;
+
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Execute hard vertical filter if semaphore for vertical deblocking
+ * is set for the current block and block immediately left of it */
+ if (((pp_mod[index-1]&0x01) != 0) && ((pp_mod[index]&0x01) != 0))
+ { /* Hard filter */
+
+ /* Set VertHflag (bit 5) in the pp_mod location of previous block*/
+ pp_mod[index-1] |= 0x20; /* 4/26/00 reuse pp_mod for VertHflag*/
+
+ /* Filter across the 8 pixels of the block */
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel
+ * and the pixel to left of it */
+ a3_0 = *ptr - *(ptr - 1);
+
+ /* if the magnitude of the difference is greater than the KThH threshold
+ * and within the quantization parameter, apply hard filter */
+ if ((a3_0 > KThH || a3_0 < -KThH) && a3_0<QP && a3_0> -QP)
+ {
+ ptr_c = ptr - 3;
+ ptr_n = ptr + 1;
+ v[0] = (int)(*(ptr_c - 3));
+ v[1] = (int)(*(ptr_c - 2));
+ v[2] = (int)(*(ptr_c - 1));
+ v[3] = (int)(*ptr_c);
+ v[4] = (int)(*(ptr_c + 1));
+
+ sum = v[0]
+ + v[1]
+ + v[2]
+ + *ptr_c
+ + v[4]
+ + (*(ptr_c + 2))
+ + (*(ptr_c + 3));
+
+ delta = (sum + *ptr_c + 4) >> 3;
+ *(ptr_c) = (uint8) delta;
+
+ /* Move pointer down one pixel to the right */
+ ptr_c += 1;
+ for (counter = 0; counter < 5; counter++)
+ {
+ /* Subtract off highest pixel and add in pixel below */
+ sum = sum - v[counter] + *ptr_n;
+ /* Average the pixel values with rounding */
+ delta = (sum + *ptr_c + 4) >> 3;
+ *ptr_c = (uint8)(delta);
+
+ /* Increment pointers to next pixel */
+ ptr_c += 1;
+ ptr_n += 1;
+ }
+ }
+ /* Increment pointers to next pixel row */
+ ptr += w1;
+ } /* index*/
+ }
+ else
+ { /* soft filter*/
+
+ /* Clear VertHflag (bit 5) in the pp_mod location */
+ pp_mod[index-1] &= 0xdf; /* reset 1101,1111 */
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel and the pixel above it */
+ a3_0 = *(ptr) - *(ptr - 1);
+
+ /* if the magnitude of the difference is greater than the KTh threshold,
+ * apply soft filter */
+ if ((a3_0 > KTh || a3_0 < -KTh))
+ {
+
+ /* Sum of weighted differences */
+ a3_0 += ((*(ptr - 2) - *(ptr + 1)) << 1) + (a3_0 << 2);
+
+ /* Check if sum is less than the quantization parameter */
+ if (PV_ABS(a3_0) < (QP << 3))
+ {
+ a3_1 = *(ptr - 2) - *(ptr - 3);
+ a3_1 += ((*(ptr - 4) - *(ptr - 1)) << 1) + (a3_1 << 2);
+
+ a3_2 = *(ptr + 2) - *(ptr + 1);
+ a3_2 += ((*(ptr) - *(ptr + 3)) << 1) + (a3_2 << 2);
+
+ A3_0 = PV_ABS(a3_0) - PV_MIN(PV_ABS(a3_1), PV_ABS(a3_2));
+
+ if (A3_0 > 0)
+ {
+ A3_0 += A3_0 << 2;
+ A3_0 = (A3_0 + 32) >> 6;
+ if (a3_0 > 0)
+ {
+ A3_0 = -A3_0;
+ }
+
+ delta = (*(ptr - 1) - *(ptr)) >> 1;
+ if (delta >= 0)
+ {
+ if (delta >= A3_0)
+ {
+ delta = PV_MAX(A3_0, 0);
+ }
+ }
+ else
+ {
+ if (A3_0 > 0)
+ {
+ delta = 0;
+ }
+ else
+ {
+ delta = PV_MAX(A3_0, delta);
+ }
+ }
+
+ *(ptr - 1) = (uint8)(*(ptr - 1) - delta);
+ *(ptr) = (uint8)(*(ptr) + delta);
+ }
+ } /*threshold*/
+ }
+ ptr += w1;
+ } /*index*/
+ } /* Soft filter*/
+ } /* boundary*/
+ } /*bc*/
+ /* Increment pointer to next row of pixels */
+ brwidth += pp_w;
+ }/*br*/
+ brwidth -= (pp_w << 1);
+
+ /****************** Deringing ***************************/
+ /* Process four blocks for the filtering */
+ /********************************************************/
+ /* Loop over two rows of blocks */
+ for (br = mbr; br < mbr + 2; br++)
+ {
+ /* Loop over two columns of blocks in the row */
+ for (bc = mbc; bc < mbc + 2; bc++)
+ {
+ /* Execute if the row and column counters are within the area */
+ if (br < pp_h && bc < pp_w)
+ {
+ /* Set the index to the current block */
+ index = brwidth + bc;
+
+ /* Execute deringing if semaphore for deringing (bit-3 of pp_mod)
+ * is set for the current block */
+ if ((pp_mod[index]&0x04) != 0)
+ {
+ /* Don't process deringing if on an edge block */
+ if (br > 0 && bc > 0 && br < pp_h - 1 && bc < pp_w - 1)
+ {
+ /* cnthflag = weighted average of HorzHflag of current,
+ * one above, previous blocks*/
+ cnthflag = ((pp_mod[index] & 0x10) +
+ (pp_mod[index-pp_w] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4; /* 4/26/00*/
+
+ /* Do the deringing if decision flags indicate it's necessary */
+ if (cnthflag < 3)
+ {
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Set amount to change luminance if it needs to be changed
+ * based on quantization parameter */
+ max_diff = (QP >> 2) + 4;
+
+ /* Set pointer to first pixel of current block */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Find minimum and maximum value of pixel block */
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+
+ /* threshold determination */
+ thres = (max_blk + min_blk + 1) >> 1;
+
+ /* If pixel range is greater or equal than DERING_THR, smooth the region */
+ if ((max_blk - min_blk) >= DERING_THR) /*smooth 8x8 region*/
+#ifndef NoMMX
+ {
+ /* smooth all pixels in the block*/
+ DeringAdaptiveSmoothMMX(ptr, width, thres, max_diff);
+ }
+#else
+ {
+ /* Setup the starting point of the region to smooth */
+ v0 = (br << 3) - 1;
+ h0 = (bc << 3) - 1;
+
+ /*smooth 8x8 region*/
+ AdaptiveSmooth_NoMMX(rec, v0, h0, v0 + 1, h0 + 1, thres, width, max_diff);
+ }
+#endif
+ }/*cnthflag*/
+ } /*dering br==1 or bc==1 (boundary block)*/
+ else /* Process the boundary blocks */
+ {
+ /* Decide to perform deblocking based on the semaphore flags
+ * of the neighboring blocks in each case. A certain number of
+ * hard filtering flags have to be set in order to signal need
+ * for smoothing */
+ if (br > 0 && br < pp_h - 1)
+ {
+ if (bc > 0)
+ {
+ cnthflag = ((pp_mod[index-pp_w] & 0x10) +
+ (pp_mod[index] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10)) >> 4;
+ }
+ else
+ {
+ cnthflag = ((pp_mod[index] & 0x10) +
+ (pp_mod[index-pp_w] & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4;
+ }
+ }
+ else if (bc > 0 && bc < pp_w - 1)
+ {
+ if (br > 0)
+ {
+ cnthflag = ((pp_mod[index-pp_w] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4;
+ }
+ else
+ {
+ cnthflag = ((pp_mod[index] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4;
+ }
+ }
+ else /* at the corner do default*/
+ {
+ cnthflag = 0;
+ }
+
+ /* Do the deringing if decision flags indicate it's necessary */
+ if (cnthflag < 2)
+ {
+
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Set amount to change luminance if it needs to be changed
+ * based on quantization parameter */
+ max_diff = (QP >> 2) + 4;
+
+ /* Set pointer to first pixel of current block */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Find minimum and maximum value of pixel block */
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+
+ /* threshold determination */
+ thres = (max_blk + min_blk + 1) >> 1;
+
+ /* Setup the starting point of the region to smooth
+ * This is going to be a 4x4 region */
+ v0 = (br << 3) + 1;
+ h0 = (bc << 3) + 1;
+
+ /* If pixel range is greater or equal than DERING_THR, smooth the region */
+ if ((max_blk - min_blk) >= DERING_THR)
+ {
+ /* Smooth 4x4 region */
+ AdaptiveSmooth_NoMMX(rec, v0, h0, v0 - 3, h0 - 3, thres, width, max_diff);
+ }
+ }/*cnthflag*/
+ } /* br==0, bc==0*/
+ } /* dering*/
+ } /*boundary condition*/
+ }/*bc*/
+ brwidth += pp_w;
+ }/*br*/
+ brwidth -= (pp_w << 1);
+ }/*mbc*/
+ brwidth += (pp_w << 1);
+ }/*mbr*/
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return ;
+}
+#endif