📄 ppclass.cpp
字号:
}
// Set control register for CSC
INSREG32BF(&m_pPpReg->PP_CNTL,
PP_CNTL_CSCEN, PP_CNTL_CSCEN_RGB);
INSREG32BF(&m_pPpReg->PP_CNTL,
PP_CNTL_CSC_OUT, pConfigData->outputFormat);
INSREG32BF(&m_pPpReg->PP_CNTL,
PP_CNTL_CSC_TABLE_SEL, pConfigData->CSCEquation);
}
PP_FUNCTION_EXIT();
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: PpConfigureResize
//
// This function configures the Post-processor resizing.
//
// Parameters:
// pConfigData
// [in] Pointer to configuration data structure
//
// Returns:
// TRUE if success; FALSE if failure.
//
//-----------------------------------------------------------------------------
BOOL PpClass::PpConfigureResize(pPpConfigData pConfigData)
{
UINT8 iRetry = 0;
UINT8 iHoriStart, iHoriEnd;
UINT8 iVertStart, iVertEnd;
FLOAT fHoriRatio, fVertRatio;
UINT16 iInWidth = pConfigData->inputSize.width;
UINT16 iInHeight = pConfigData->inputSize.height;
UINT16 iOutWidth = pConfigData->outputSize.width;
UINT16 iOutHeight = pConfigData->outputSize.height;
UINT16 iVarInWidth, iVarOutWidth;
UINT16 iVarInHeight, iVarOutHeight;
PP_FUNCTION_ENTRY();
// Only support 2:1 to 1:4 and a fixed 4:1
if (((4 * iInWidth < iOutWidth) || (iInWidth > 2 * iOutWidth)) &&
(iInWidth != 4 * iOutWidth)) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Invalid width resizing ratio\r\n"), __WFUNCTION__));
return FALSE;
}
if (((4 * iInHeight < iOutHeight) || (iInHeight > 2 * iOutHeight)) &&
(iInHeight != 4 * iOutHeight)) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Invalid height resizing ratio\r\n"), __WFUNCTION__));
return FALSE;
}
//
// Resizing ratio calculation
//
m_iHoriLen = 0;
m_iVertLen = 0;
// Width
if (iInWidth != iOutWidth) {
iVarInWidth = iInWidth;
iVarOutWidth = iOutWidth;
while (iRetry < PP_MAX_RESIZE_RETRIES) {
UINT16 gcd = PpGetGcd(iVarInWidth, iVarOutWidth);
m_iHoriLen = PpResize(iVarInWidth/gcd, iVarOutWidth/gcd);
if (m_iHoriLen < 0) {
iRetry++;
iVarOutWidth++;
m_iHoriLen = 0;
}
else break;
}
} else {
// Calculate it even for 1:1
m_iHoriLen = PpResize(1, 1);
if (m_iHoriLen < 0) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Width 1:1 resize calculation failure\r\n"),
__WFUNCTION__));
return FALSE;
}
}
if (iRetry == PP_MAX_RESIZE_RETRIES) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Width resize failure\r\n"), __WFUNCTION__));
return FALSE;
}
iHoriStart = 0;
iHoriEnd = m_iHoriLen - 1;
// Height
iRetry = 0;
fHoriRatio = (iInWidth > iOutWidth) ?
((float)iInWidth / (float)iOutWidth) :
((float)iOutWidth / (float)iInWidth);
fVertRatio = (iInHeight > iOutHeight) ?
((float)iInHeight / (float)iOutHeight) :
((float)iOutHeight / (float)iInHeight);
if (fHoriRatio != fVertRatio) {
if (iInHeight != iOutHeight) {
// UINT16 inHeight = iInHeight;
iVarInHeight = iInHeight;
iVarOutHeight = iOutHeight;
while (iRetry < PP_MAX_RESIZE_RETRIES) {
UINT16 gcd = PpGetGcd(iVarInHeight, iVarOutHeight);
m_iVertLen = PpResize(iVarInHeight/gcd, iVarOutHeight/gcd);
if (m_iVertLen < 0) {
iRetry++;
iVarOutHeight++;
m_iVertLen = 0;
} else break;
}
} else {
// Calculate it even for 1:1
m_iVertLen = PpResize(1, 1);
if (m_iVertLen < 0) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Height 1:1 resize calculation failure\r\n"),
__WFUNCTION__));
return FALSE;
}
}
if (iRetry == PP_MAX_RESIZE_RETRIES) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Width resize failure\r\n"), __WFUNCTION__));
return FALSE;
}
iVertStart = m_iHoriLen;
iVertEnd = m_iHoriLen + m_iVertLen - 1;
} else {
iVertStart = iHoriStart;
iVertEnd = iHoriEnd;
}
PpSetupResize(iVertStart, iVertEnd, iHoriStart, iHoriEnd);
PP_FUNCTION_EXIT();
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: PpGetGcd
//
// This function is used to calculate the greatest common divider of the
// two passed in parameters. This code is reused from Symbian.
//
// Parameters:
// x
// [in] One number.
//
// y
// [in] The other one.
//
// Returns:
// The greatest common divider of x and y.
//
//------------------------------------------------------------------------------
UINT16 PpClass::PpGetGcd(UINT16 x, UINT16 y)
{
UINT16 temp;
if (x < y) {
temp = y;
y = x;
x = temp;
}
if ((x % y) == 0) return y;
while ((temp = (x % y)) != 0) {
x = y;
y = temp;
}
return y;
}
//------------------------------------------------------------------------------
//
// Function: PpResize
//
// This function is used to build resize table. Bilinear interpolation is
// implemented. There is a special case for 4:1 scaling.
//
// This code is reused from Symbian team.
//
// Parameters:
// in
// [in] Width/height of input frame.
//
// out
// [in] Width/height of output frame.
//
// Returns:
// Resized width/height if positive otherwise indicates failure.
//
//------------------------------------------------------------------------------
INT8 PpClass::PpResize(UINT16 in, UINT16 out)
{
UINT8 iResizeLen = 0;
// Up sampling
if (in <= out) {
UINT16 pos = 0;
for (UINT16 i = 0; i < out; i++) {
UINT16 w1 = out - pos;
UINT16 w2 = pos;
UINT16 next = 0;
pos += in;
if (pos >= out) {
pos -= out;
next++;
}
if ((iResizeLen + m_iHoriLen) >= PP_MAX_RESIZE_COEFFS) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Up sampling exceeds maximum coeffs\r\n"),
__WFUNCTION__));
return (-1);
}
PpStoreCoeffs(w1, w2, out, next, iResizeLen);
iResizeLen++;
if (pos == 0) break;
}
} else if (in <= 2 * out) {
// Handle the cases for 2:1 and lower for down sampling
UINT16 inPos1 = out;
UINT16 inPosInc = 2 * out;
UINT16 inPos2 = inPos1 + inPosInc;
UINT16 outPos = in;
UINT16 outPosInc = 2 * in;
UINT16 init_carry = in - out;
UINT16 carry = init_carry;
do {
int w1 = inPos2 - outPos;
int w2 = outPos - inPos1;
int n = 0;
outPos += outPosInc;
carry += outPosInc;
while (inPos2 < outPos) {
inPos1 = inPos2;
inPos2 += inPosInc;
n++;
carry -= inPosInc;
}
if ((iResizeLen + m_iHoriLen) >= PP_MAX_RESIZE_COEFFS) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Down sampling exceeds maximum coeffs\r\n"),
__WFUNCTION__));
return (-1);
}
PpStoreCoeffs(w1, w2, 2 * out, n, iResizeLen);
iResizeLen++;
} while (carry != init_carry);
} else if (in == 4 * out) {
// Down sampling by 4:1
m_iResizeCoeffs[m_iHoriLen] =
CSP_BITFVAL(PP_RESIZE_COEF_TBL_W, ((1 << PP_RESIZE_COEFF) / 2)) |
CSP_BITFVAL(PP_RESIZE_COEF_TBL_N, 1) |
CSP_BITFVAL(PP_RESIZE_COEF_TBL_OP, PP_RESIZE_COEF_TBL_OP_PIXELS);
m_iResizeCoeffs[m_iHoriLen + 1] = CSP_BITFVAL(PP_RESIZE_COEF_TBL_N, 1) |
CSP_BITFVAL(PP_RESIZE_COEF_TBL_OP, PP_RESIZE_COEF_TBL_OP_NOPIXELS);
m_iResizeCoeffs[m_iHoriLen + 2] = CSP_BITFVAL(PP_RESIZE_COEF_TBL_N, 1) |
CSP_BITFVAL(PP_RESIZE_COEF_TBL_OP, PP_RESIZE_COEF_TBL_OP_NOPIXELS);
m_iResizeCoeffs[m_iHoriLen + 3] = CSP_BITFVAL(PP_RESIZE_COEF_TBL_N, 1) |
CSP_BITFVAL(PP_RESIZE_COEF_TBL_OP, PP_RESIZE_COEF_TBL_OP_NOPIXELS);
iResizeLen = 4;
} else {
// The resize ratio is not supported
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Unsupported resizing ratio\r\n"),
__WFUNCTION__));
return (-1);
}
return iResizeLen;
}
//------------------------------------------------------------------------------
//
// Function: PpStoreCoeffs
//
// This function is used to store the resizing instructions in the array
// m_iResizeCoeffs[]. Each entry in the array is in the form (w1, w2, n).
// An output pixel will be generated with the value (w1*in1 + w2*in2) and
// the resize engine will then read in a n new input pixels (where n != 0),
// where in1 and in2 are two adjacent pixels.
//
// This code is reused from Symbian team.
//
// Parameters:
// ...
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void PpClass::PpStoreCoeffs(UINT16 w1, UINT16 w2, UINT16 base,
UINT16 next, UINT16 index)
{
UINT16 iCoeff;
if (m_iHoriLen != 0)
index += m_iHoriLen;
iCoeff = ((w1 << PP_RESIZE_COEFF) + (base >> 1)) / base;
// 31 means 32, so 30 will handle both 30 & 31
if (iCoeff == (PP_MAX_COEFF - 1))
iCoeff--;
else if (iCoeff == 1)
iCoeff++;
else if (iCoeff == PP_MAX_COEFF)
// 32 should be set to 31, as the HW treats 31 binary as 32 decimal
iCoeff = PP_MAX_COEFF - 1;
m_iResizeCoeffs[index] = CSP_BITFVAL(PP_RESIZE_COEF_TBL_W, iCoeff) |
CSP_BITFVAL(PP_RESIZE_COEF_TBL_N, next) |
CSP_BITFVAL(PP_RESIZE_COEF_TBL_OP, PP_RESIZE_COEF_TBL_OP_PIXELS);
}
//------------------------------------------------------------------------------
//
// Function: PpSetupResize
//
// This function is used to setup the resize registers.
//
// Parameters:
// iVertStart
// [in] Start index of vertial resize table.
//
// iVertEnd
// [in] End index of vertial resize table.
//
// iHoriStart
// [in] Start index of horizontal resize table.
//
// iHoriEnd
// [in] End index of horizontal resize table.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void PpClass::PpSetupResize(UINT8 iVertStart, UINT8 iVertEnd,
UINT8 iHoriStart, UINT8 iHoriEnd)
{
UINT16 len;
UINT16 i;
// Setup RESIZE_TBL_INDEX regiser
OUTREG32(&m_pPpReg->PP_RESIZE_TABLE_INDEX,
CSP_BITFVAL(PP_RESIZE_TABLE_INDEX_VERT_TBL_END_INDEX, iVertEnd) |
CSP_BITFVAL(PP_RESIZE_TABLE_INDEX_VERT_TBL_START_INDEX, iVertStart) |
CSP_BITFVAL(PP_RESIZE_TABLE_INDEX_HORI_TBL_END_INDEX, iHoriEnd) |
CSP_BITFVAL(PP_RESIZE_TABLE_INDEX_HORI_TBL_START_INDEX, iHoriStart));
// Setup RESIZE_TABLE register
if ((iVertEnd != iHoriEnd) && (iVertStart != iHoriStart)) {
len = (iVertEnd - iVertStart) + (iHoriEnd - iHoriStart) + 2;
} else {
// If the horizontal and vertical resize ratios are the same,
// then the iHoriStart can be the same as iVertStart and iHoriEnd
// can be the same as iVertEnd.
len = iVertEnd - iVertStart + 1;
}
for (i = 0; i < len; i++)
OUTREG32(&m_pPpReg->PP_RESIZE_COEF_TBL[i], m_iResizeCoeffs[i]);
}
//-----------------------------------------------------------------------------
//
// Function: PpEnqueueBuffers
//
// This function adds buffers for the PP channel. Input and output buffers
// are provided and added to the buffer queue. It is assumed that the caller
// has allocated physically contiguous buffers.
//
// Parameters:
// pPpBufs
// [in] Pointer to structure containing a pointer to an input and
// output buffer.
//
// Returns:
// TRUE if successful; FALSE if failed.
//
//-----------------------------------------------------------------------------
BOOL PpClass::PpEnqueueBuffers(pPpBuffers pPpBufs)
{
PP_FUNCTION_ENTRY();
//
// Buffer boundary check
// QP is needed only when deblock and/or dering enabled
// Input, output and quantizer buffer should be word aligned
//
if (m_bNeedQP) {
if ((pPpBufs->InQPBuf == NULL) ||
(((UINT32)(pPpBufs->InQPBuf) & 0x03) != 0)) {
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Invalid quantizer buffer (0x%08lX).\r\n"),
__WFUNCTION__, pPpBufs->InQPBuf));
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -