📄 swdec_processblock.c
字号:
row += verMv;
#ifdef MP4DEC_H263_ONLY
SwDec_GetBlock(pRef, pOut, col, row,
pDecContainer->VopDesc.vopWidth * 8,
pDecContainer->VopDesc.vopWidth * 8,
pDecContainer->VopDesc.vopHeight * 8, 1);
#else
SwDec_GetBlock(pRef, pOut, col, row,
pDecContainer->VopDesc.vopWidth * 8,
pDecContainer->VopDesc.vopWidth * 8,
pDecContainer->VopDesc.vopHeight * 8,
(u32)(pDecContainer->VopDesc.vopRoundingType != 1));
#endif
}
}
/*------------------------------------------------------------------------------
5.4 Function name: SwDec_ChrMv
Purpose: Compute chrominance motion vector based on luminance motion
vectors
Input:
motionVectors pointer to 4 luminance motion vectors (4 pairs,
hor,ver,hor,ver,hor,ver,hor,ver)
chrHorMv pointer to horizontal chr motion vector
chrVerMv pointer to vertical chr motion vector
Output:
------------------------------------------------------------------------------*/
void SwDec_ChrMv(i16 *motionVectors, i32 *chrHorMv, i32 *chrVerMv)
{
i32 tmp;
static const i32 roundingTable[16] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2};
ASSERT(motionVectors);
ASSERT(chrHorMv);
ASSERT(chrVerMv);
/* Sum of four motion vector */
*chrHorMv = motionVectors[0] + motionVectors[2] +
motionVectors[4] + motionVectors[6];
tmp = (*chrHorMv < 0) ? -(*chrHorMv) : (*chrHorMv);
tmp = ((tmp>>4)<<1) + roundingTable[tmp & 0xF];
if (*chrHorMv < 0)
*chrHorMv = -tmp;
else
*chrHorMv = tmp;
/* Sum of four motion vector */
*chrVerMv = motionVectors[1] + motionVectors[3] +
motionVectors[5] + motionVectors[7];
tmp = (*chrVerMv < 0) ? -(*chrVerMv) : (*chrVerMv);
tmp = ((tmp>>4)<<1) + roundingTable[tmp & 0xF];
if (*chrVerMv < 0)
*chrVerMv = -tmp;
else
*chrVerMv = tmp;
}
/*------------------------------------------------------------------------------
5.5 Function name: SwDec_GetBlock
Purpose: Get reference block for motion compensation
Input:
u8 *pRef pointer to reference image
u8 *pOut pointer to output block
i32 hosPos horizontal position in reference picture
i32 verPos vertical position in reference picture
u32 refWidth width of reference picture (whole macro blocks)
u32 width width of the actual picture (half pixel precision)
u32 height height of the actual picture (half pixel precision)
u32 round rounding control (should be 1-vop_rounding_type)
Output:
------------------------------------------------------------------------------*/
void SwDec_GetBlock(u8 *pRef,u8 *pOut, i32 horPos, i32 verPos, u32 refWidth,
u32 width, u32 height, u32 round)
{
i32 tmpx, tmpy;
u32 interpolationCase;
i32 row, lastRow;
/* to ensure that fill is at word boundary */
u32 fill[27];
u8 *pFill = (u8*)fill;
/* Limit horizontal position */
SATURATE(-16, horPos, (i32)(2*width-2));
/* Limit vertical position */
SATURATE(-16, verPos, (i32)(2*height-2));
/* determine full pixel position */
tmpx = horPos>>1;
tmpy = verPos>>1;
interpolationCase = ((verPos&0x1)<<1) + (horPos&0x1);
/* No overfill needed -> just interpolate if necessary */
if ( (width >= 8) && ((u32)(horPos) < (2*width - 15)) &&
(height >= 8) && ((u32)(verPos) < (2*height - 15)) )
{
pRef += (u32)tmpx + (u32)tmpy*width;
if(interpolationCase == 0)
SwDec_InterpolateNone(pRef, pOut, refWidth);
else if(interpolationCase == 1)
SwDec_InterpolateHorizontal(pRef, pOut, refWidth, round);
else if(interpolationCase == 2)
SwDec_InterpolateVertical(pRef, pOut, refWidth, round);
else
SwDec_InterpolateBoth(pRef, pOut, refWidth, round);
}
/* overfill and interpolation */
else
{
row = tmpy;
lastRow = tmpy + 9;
/* Fill buffer "fill" so that it contains 9x9 elements to make interpolation
* possible */
/* overfill top */
for (;row < 0; row++)
{
SwDec_FillRow(pRef, pFill, tmpx, width);
pFill += 12;
}
pRef += row * (i32)refWidth;
for (; row < lastRow; row++)
{
SwDec_FillRow(pRef, pFill, tmpx, width);
pFill += 12;
/* skip increment for overfill bottom */
if (row < (i32)(height-1))
{
pRef += refWidth;
}
}
pFill = (u8*)fill;
if(interpolationCase == 0)
SwDec_InterpolateNone(pFill, pOut, 12);
else if(interpolationCase == 1)
SwDec_InterpolateHorizontal(pFill, pOut, 12, round);
else if(interpolationCase == 2)
SwDec_InterpolateVertical(pFill, pOut, 12, round);
else
SwDec_InterpolateBoth(pFill, pOut, 12, round);
}
}
/*------------------------------------------------------------------------------
5.6 Function name: SwDec_FillRow
Purpose: Perform overfilling for one row if necessary
Input:
u8 *pRef pointer to reference picture (where data is taken from)
u8 *fill pointer to (partial, 9 pixels) overfilled row
i32 horPos horizontal position in reference picture
u32 width width of the reference picture (in pixels)
Output:
------------------------------------------------------------------------------*/
void SwDec_FillRow(u8 *pRef, u8 *fill, i32 horPos, u32 width)
{
i32 last;
ASSERT(pRef);
ASSERT(fill);
ASSERT(width);
ASSERT(horPos < (i32)width);
last = horPos + 9;
for (; horPos < 0; horPos++) {
*fill++ = *pRef;
}
pRef += horPos;
for (; horPos < last; horPos++) {
*fill++ = *pRef;
if (horPos < (i32)(width-1))
pRef++;
}
}
/*------------------------------------------------------------------------------
5.7 Function name: SwDec_InterpolateNone
Purpose: Interpolate data in reference picture if necessary
Input:
pRef pointer to reference picture
pOut pointer to interpolated block
width width of reference picture in pixels (whole macro
blocks)
round rounding control (should be 1-vop_rounding_type)
Output:
------------------------------------------------------------------------------*/
void SwDec_InterpolateNone(u8 *pRef, u8 *pOut, u32 width)
{
u32 i;
u32 *pRef32;
u32 *pOut32;
#ifndef MP4DEC_UNALIGNED
u32 tmp1,tmp2,tmp3,tmp4;
#else
u32 tmp1,tmp2,tmp;
#endif
ASSERT(pRef);
ASSERT(pOut);
ASSERT(width >= 8);
#ifndef MP4DEC_UNALIGNED
pOut32 = (u32*)pOut;
/* at word boundary you can copy as u32 */
if (((u32)pRef & 0x3) == 0)
{
pRef32 = (u32*)pRef;
tmp3 = (width>>2)-1;
for(i = 8; i; i--)
{
tmp1 = *pRef32++;
tmp2 = *pRef32;
*pOut32++ = tmp1;
*pOut32++ = tmp2;
pRef32 += tmp3;
}
}
/* read as u8 and write as u8 */
else
{
for(i = 8; i; i--)
{
tmp1 = *pRef++;
tmp2 = *pRef++;
tmp3 = *pRef++;
tmp4 = *pRef++;
*pOut++ = (u8)tmp1;
*pOut++ = (u8)tmp2;
*pOut++ = (u8)tmp3;
*pOut++ = (u8)tmp4;
tmp1 = *pRef++;
tmp2 = *pRef++;
tmp3 = *pRef++;
tmp4 = *pRef;
*pOut++ = (u8)tmp1;
*pOut++ = (u8)tmp2;
*pOut++ = (u8)tmp3;
*pOut++ = (u8)tmp4;
pRef += (width-7);
}
}
#else
/* use unaligned support to read
* and write on word at a time */
pOut32 = (u32*)pOut;
pRef32 = (u32*)pRef;
tmp = (width>>2)-1;
for(i = 4; i; i--)
{
tmp1 = *pRef32++;
*pOut32++ = tmp1;
tmp2 = *pRef32;
*pOut32++ = tmp2;
pRef32 += tmp;
tmp1 = *pRef32++;
*pOut32++ = tmp1;
tmp2 = *pRef32;
*pOut32++ = tmp2;
pRef32 += tmp;
}
#endif
}
/*------------------------------------------------------------------------------
5.8 Function name: SwDec_InterpolateVertical
Purpose: Interpolate data in reference picture if necessary
Input:
pRef pointer to reference picture
pOut pointer to interpolated block
width width of reference picture in pixels (whole macro
blocks)
round rounding control (should be 1-vop_rounding_type)
Output:
Interpolation of MB in vertical direction:
| xxxx++++ |
| oooo++++ |
| ++++++++ |
| ++++++++ |
| ++++++++ |
| ++++++++ |
| ++++++++ |
| ++++++++ |
| @@@@@@@@ |
Interpolation is done by bytewise x-o for four pixels at time if pRef is
at word boundary in memory. Calculation is done as u32 instead of u8. At
the beginning pRef points to the first x in picture above and ptmp points
to the first o in picture above. Then pRef is incremented so that it
points to beginning of the row three. o's stays in temprorary variable
and then we interpolate bytewise o-x four pixels at time.
Used algorithm:
if ( rounding_control = 1)
A/2 + B/2 + [(A & B) & 1]
else (rounding_control = 0)
A/2 + B/2 + [(A | B ) & 1]
------------------------------------------------------------------------------*/
void SwDec_InterpolateVertical(u8 *pRef, u8 *pOut, u32 width, u32 round)
{
u32 i;
u32 tmp1,tmp3;
u32 tmp2=0, tmp4=0;
#if !defined(MP4DEC_ARM11) || !defined(MP4DEC_UNALIGNED)
u32 *pRef32;
u32 *ptmp32;
u8 *ptmp;
u32 *pOut32;
#else
u32 tmpx,tmpy,c1;
#endif
ASSERT(pRef);
ASSERT(pOut);
ASSERT(width >= 8);
ASSERT(round <= 1);
#if !defined(MP4DEC_ARM11) || !defined(MP4DEC_UNALIGNED)
ptmp = pRef + width;
pOut32 = (u32*)pOut;
/* check if the pRef is at word boundary */
if (((u32)pRef & 0x3) == 0)
{
pRef32 = (u32*)pRef;
ptmp32 = (u32*)ptmp;
/* read one row */
tmp1 = (*pRef32++);
tmp3 = (*pRef32++);
/* skip one row */
pRef32 += ((width>>1)-2);
if (round == 0)
{
for ( i = 8; i; i--)
{
if (i & 0x1)
{
/* read one row */
tmp1 = (*pRef32++);
tmp3 = (*pRef32++);
/* skip one row */
pRef32 += ((width>>1)-2);
}
else
{
/* read one row */
tmp2 = (*ptmp32++);
tmp4 = (*ptmp32++);
/* skip one row */
ptmp32 += ((width>>1)-2);
}
/* interpolate */
*pOut32++ = (((tmp1>>1) & 0x7F7F7F7F) + ((tmp2>>1) & 0x7F7F7F7F)
+ (( tmp1 & tmp2) & 0x01010101));
*pOut32++ = (((tmp3>>1) & 0x7F7F7F7F) + ((tmp4>>1) & 0x7F7F7F7F)
+ (( tmp3 & tmp4) & 0x01010101));
}
}
else
{
for ( i = 8; i; i--)
{
if (i & 0x1)
{
/* read one row */
tmp1 = (*pRef32++);
tmp3 = (*pRef32++);
/* skip one row */
pRef32 += ((width>>1)-2);
}
else
{
/* read one row */
tmp2 = (*ptmp32++);
tmp4 = (*ptmp32++);
/* skip one row */
ptmp32 += ((width>>1)-2);
}
/* interpolate four pixels at once */
*pOut32++ = (((tmp1>>1) & 0x7F7F7F7F) + ((tmp2>>1) & 0x7F7F7F7F)
+ (( tmp1 | tmp2) & 0x01010101));
*pOut32++ = (((tmp3>>1) & 0x7F7F7F7F) + ((tmp4>>1) & 0x7F7F7F7F)
+ (( tmp3 | tmp4) & 0x01010101));
}
}
}
/* if pRef is not at word boundary */
else
{
for( i = 8; i; i--)
{
tmp1 = *pRef++;
tmp3 = *pRef++;
tmp2 = *ptmp++;
tmp4 = *ptmp++;
*pOut++ = (u8)((round+tmp1+tmp2)>>1);
tmp1 = *pRef++;
tmp2 = *ptmp++;
*pOut++ = (u8)((tmp3+tmp4+round)>>1);
tmp3 = *pRef++;
tmp4 = *ptmp++;
*pOut++ = (u8)((tmp1+tmp2+round)>>1);
tmp1 = *pRef++;
tmp2 = *ptmp++;
*pOut++ = (u8)((tmp3+tmp4+round)>>1);
tmp3 = *pRef++;
tmp4 = *ptmp++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -