blob: b36050c5af0add8b75787f648cba2fafe3e0ecc6 [file] [log] [blame]
/* ------------------------------------------------------------------
* 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"
#ifdef PV_ANNEX_IJKT_SUPPORT
#include "motion_comp.h"
#include "mbtype_mode.h"
const static int STRENGTH_tab[] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12};
#endif
#ifdef PV_POSTPROC_ON
/*----------------------------------------------------------------------------
; FUNCTION CODE
----------------------------------------------------------------------------*/
void PostFilter(
VideoDecData *video,
int filter_type,
uint8 *output)
{
/*----------------------------------------------------------------------------
; Define all local variables
----------------------------------------------------------------------------*/
uint8 *pp_mod;
int16 *QP_store;
int combined_with_deblock_filter;
int nTotalMB = video->nTotalMB;
int width, height;
int32 size;
int softDeblocking;
uint8 *decodedFrame = video->videoDecControls->outputFrame;
/*----------------------------------------------------------------------------
; Function body here
----------------------------------------------------------------------------*/
width = video->width;
height = video->height;
size = (int32)width * height;
oscl_memcpy(output, decodedFrame, size);
oscl_memcpy(output + size, decodedFrame + size, (size >> 2));
oscl_memcpy(output + size + (size >> 2), decodedFrame + size + (size >> 2), (size >> 2));
if (filter_type == 0)
return;
/* The softDecoding cutoff corresponds to ~93000 bps for QCIF 15fps clip */
if (PVGetDecBitrate(video->videoDecControls) > (100*video->frameRate*(size >> 12))) // MC_sofDeblock
softDeblocking = FALSE;
else
softDeblocking = TRUE;
combined_with_deblock_filter = filter_type & PV_DEBLOCK;
QP_store = video->QPMB;
/* Luma */
pp_mod = video->pstprcTypCur;
if ((filter_type & PV_DEBLOCK) && (filter_type & PV_DERING))
{
CombinedHorzVertRingFilter(output, width, height, QP_store, 0, pp_mod);
}
else
{
if (filter_type & PV_DEBLOCK)
{
if (softDeblocking)
{
CombinedHorzVertFilter(output, width, height,
QP_store, 0, pp_mod);
}
else
{
CombinedHorzVertFilter_NoSoftDeblocking(output, width, height,
QP_store, 0, pp_mod);
}
}
if (filter_type & PV_DERING)
{
Deringing_Luma(output, width, height, QP_store,
combined_with_deblock_filter, pp_mod);
}
}
/* Chroma */
pp_mod += (nTotalMB << 2);
output += size;
if ((filter_type & PV_DEBLOCK) && (filter_type & PV_DERING))
{
CombinedHorzVertRingFilter(output, (int)(width >> 1), (int)(height >> 1), QP_store, (int) 1, pp_mod);
}
else
{
if (filter_type & PV_DEBLOCK)
{
if (softDeblocking)
{
CombinedHorzVertFilter(output, (int)(width >> 1),
(int)(height >> 1), QP_store, (int) 1, pp_mod);
}
else
{
CombinedHorzVertFilter_NoSoftDeblocking(output, (int)(width >> 1),
(int)(height >> 1), QP_store, (int) 1, pp_mod);
}
}
if (filter_type & PV_DERING)
{
Deringing_Chroma(output, (int)(width >> 1),
(int)(height >> 1), QP_store,
combined_with_deblock_filter, pp_mod);
}
}
pp_mod += nTotalMB;
output += (size >> 2);
if ((filter_type & PV_DEBLOCK) && (filter_type & PV_DERING))
{
CombinedHorzVertRingFilter(output, (int)(width >> 1), (int)(height >> 1), QP_store, (int) 1, pp_mod);
}
else
{
if (filter_type & PV_DEBLOCK)
{
if (softDeblocking)
{
CombinedHorzVertFilter(output, (int)(width >> 1),
(int)(height >> 1), QP_store, (int) 1, pp_mod);
}
else
{
CombinedHorzVertFilter_NoSoftDeblocking(output, (int)(width >> 1),
(int)(height >> 1), QP_store, (int) 1, pp_mod);
}
}
if (filter_type & PV_DERING)
{
Deringing_Chroma(output, (int)(width >> 1),
(int)(height >> 1), QP_store,
combined_with_deblock_filter, pp_mod);
}
}
/* swap current pp_mod to prev_frame pp_mod */
pp_mod = video->pstprcTypCur;
video->pstprcTypCur = video->pstprcTypPrv;
video->pstprcTypPrv = pp_mod;
/*----------------------------------------------------------------------------
; Return nothing or data or data pointer
----------------------------------------------------------------------------*/
return;
}
#endif
#ifdef PV_ANNEX_IJKT_SUPPORT
void H263_Deblock(uint8 *rec,
int width,
int height,
int16 *QP_store,
uint8 *mode,
int chr, int annex_T)
{
/*----------------------------------------------------------------------------
; Define all local variables
----------------------------------------------------------------------------*/
int i, j, k;
uint8 *rec_y;
int tmpvar;
int mbnum, strength, A_D, d1_2, d1, d2, A, B, C, D, b_size;
int d, offset, nMBPerRow, nMBPerCol, width2 = (width << 1);
/* MAKE SURE I-VOP INTRA MACROBLOCKS ARE SET TO NON-SKIPPED MODE*/
mbnum = 0;
if (chr)
{
nMBPerRow = width >> 3;
nMBPerCol = height >> 3;
b_size = 8;
}
else
{
nMBPerRow = width >> 4;
nMBPerCol = height >> 4;
b_size = 16;
}
/********************************* VERTICAL FILTERING ****************************/
/* vertical filtering of mid sections no need to check neighboring QP's etc */
if (!chr)
{
rec_y = rec + (width << 3);
for (i = 0; i < (height >> 4); i++)
{
for (j = 0; j < (width >> 4); j++)
{
if (mode[mbnum] != MODE_SKIPPED)
{
k = 16;
strength = STRENGTH_tab[QP_store[mbnum]];
while (k--)
{
A = *(rec_y - width2);
D = *(rec_y + width);
A_D = A - D;
C = *rec_y;
B = *(rec_y - width);
d = (((C - B) << 2) + A_D);
if (d < 0)
{
d1 = -(-d >> 3);
if (d1 < -(strength << 1))
{
d1 = 0;
}
else if (d1 < -strength)
{
d1 = -d1 - (strength << 1);
}
d1_2 = -d1 >> 1;
}
else
{
d1 = d >> 3;
if (d1 > (strength << 1))
{
d1 = 0;
}
else if (d1 > strength)
{
d1 = (strength << 1) - d1;
}
d1_2 = d1 >> 1;
}
if (A_D < 0)
{
d2 = -(-A_D >> 2);
if (d2 < -d1_2)
{
d2 = -d1_2;
}
}
else
{
d2 = A_D >> 2;
if (d2 > d1_2)
{
d2 = d1_2;
}
}
*(rec_y - width2) = A - d2;
tmpvar = B + d1;
CLIP_RESULT(tmpvar)
*(rec_y - width) = tmpvar;
tmpvar = C - d1;
CLIP_RESULT(tmpvar)
*rec_y = tmpvar;
*(rec_y + width) = D + d2;
rec_y++;
}
}
else
{
rec_y += b_size;
}
mbnum++;
}
rec_y += (15 * width);
}
}
/* VERTICAL boundary blocks */
rec_y = rec + width * b_size;
mbnum = nMBPerRow;
for (i = 0; i < nMBPerCol - 1; i++)
{
for (j = 0; j < nMBPerRow; j++)
{
if (mode[mbnum] != MODE_SKIPPED || mode[mbnum - nMBPerRow] != MODE_SKIPPED)
{
k = b_size;
if (mode[mbnum] != MODE_SKIPPED)
{
strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum]] : QP_store[mbnum])];
}
else
{
strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum - nMBPerRow]] : QP_store[mbnum - nMBPerRow])];
}
while (k--)
{
A = *(rec_y - width2);
D = *(rec_y + width);
A_D = A - D;
C = *rec_y;
B = *(rec_y - width);
d = (((C - B) << 2) + A_D);
if (d < 0)
{
d1 = -(-d >> 3);
if (d1 < -(strength << 1))
{
d1 = 0;
}
else if (d1 < -strength)
{
d1 = -d1 - (strength << 1);
}
d1_2 = -d1 >> 1;
}
else
{
d1 = d >> 3;
if (d1 > (strength << 1))
{
d1 = 0;
}
else if (d1 > strength)
{
d1 = (strength << 1) - d1;
}
d1_2 = d1 >> 1;
}
if (A_D < 0)
{
d2 = -(-A_D >> 2);
if (d2 < -d1_2)
{
d2 = -d1_2;
}
}
else
{
d2 = A_D >> 2;
if (d2 > d1_2)
{
d2 = d1_2;
}
}
*(rec_y - width2) = A - d2;
tmpvar = B + d1;
CLIP_RESULT(tmpvar)
*(rec_y - width) = tmpvar;
tmpvar = C - d1;
CLIP_RESULT(tmpvar)
*rec_y = tmpvar;
*(rec_y + width) = D + d2;
rec_y++;
}
}
else
{
rec_y += b_size;
}
mbnum++;
}
rec_y += ((b_size - 1) * width);
}
/***************************HORIZONTAL FILTERING ********************************************/
mbnum = 0;
/* HORIZONTAL INNER */
if (!chr)
{
rec_y = rec + 8;
offset = width * b_size - b_size;
for (i = 0; i < nMBPerCol; i++)
{
for (j = 0; j < nMBPerRow; j++)
{
if (mode[mbnum] != MODE_SKIPPED)
{
k = 16;
strength = STRENGTH_tab[QP_store[mbnum]];
while (k--)
{
A = *(rec_y - 2);
D = *(rec_y + 1);
A_D = A - D;
C = *rec_y;
B = *(rec_y - 1);
d = (((C - B) << 2) + A_D);
if (d < 0)
{
d1 = -(-d >> 3);
if (d1 < -(strength << 1))
{
d1 = 0;
}
else if (d1 < -strength)
{
d1 = -d1 - (strength << 1);
}
d1_2 = -d1 >> 1;
}
else
{
d1 = d >> 3;
if (d1 > (strength << 1))
{
d1 = 0;
}
else if (d1 > strength)
{
d1 = (strength << 1) - d1;
}
d1_2 = d1 >> 1;
}
if (A_D < 0)
{
d2 = -(-A_D >> 2);
if (d2 < -d1_2)
{
d2 = -d1_2;
}
}
else
{
d2 = A_D >> 2;
if (d2 > d1_2)
{
d2 = d1_2;
}
}
*(rec_y - 2) = A - d2;
tmpvar = B + d1;
CLIP_RESULT(tmpvar)
*(rec_y - 1) = tmpvar;
tmpvar = C - d1;
CLIP_RESULT(tmpvar)
*rec_y = tmpvar;
*(rec_y + 1) = D + d2;
rec_y += width;
}
rec_y -= offset;
}
else
{
rec_y += b_size;
}
mbnum++;
}
rec_y += (15 * width);
}
}
/* HORIZONTAL EDGE */
rec_y = rec + b_size;
offset = width * b_size - b_size;
mbnum = 1;
for (i = 0; i < nMBPerCol; i++)
{
for (j = 0; j < nMBPerRow - 1; j++)
{
if (mode[mbnum] != MODE_SKIPPED || mode[mbnum-1] != MODE_SKIPPED)
{
k = b_size;
if (mode[mbnum] != MODE_SKIPPED)
{
strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum]] : QP_store[mbnum])];
}
else
{
strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum - 1]] : QP_store[mbnum - 1])];
}
while (k--)
{
A = *(rec_y - 2);
D = *(rec_y + 1);
A_D = A - D;
C = *rec_y;
B = *(rec_y - 1);
d = (((C - B) << 2) + A_D);
if (d < 0)
{
d1 = -(-d >> 3);
if (d1 < -(strength << 1))
{
d1 = 0;
}
else if (d1 < -strength)
{
d1 = -d1 - (strength << 1);
}
d1_2 = -d1 >> 1;
}
else
{
d1 = d >> 3;
if (d1 > (strength << 1))
{
d1 = 0;
}
else if (d1 > strength)
{
d1 = (strength << 1) - d1;
}
d1_2 = d1 >> 1;
}
if (A_D < 0)
{
d2 = -(-A_D >> 2);
if (d2 < -d1_2)
{
d2 = -d1_2;
}
}
else
{
d2 = A_D >> 2;
if (d2 > d1_2)
{
d2 = d1_2;
}
}
*(rec_y - 2) = A - d2;
tmpvar = B + d1;
CLIP_RESULT(tmpvar)
*(rec_y - 1) = tmpvar;
tmpvar = C - d1;
CLIP_RESULT(tmpvar)
*rec_y = tmpvar;
*(rec_y + 1) = D + d2;
rec_y += width;
}
rec_y -= offset;
}
else
{
rec_y += b_size;
}
mbnum++;
}
rec_y += ((width * (b_size - 1)) + b_size);
mbnum++;
}
return;
}
#endif