mcomp.c
来自「symbian 下的helix player源代码」· C语言 代码 · 共 1,603 行 · 第 1/5 页
C
1,603 行
pIn.pix = outBegin;
pOut.pix = outSave;
for (y = 0; y < repeatTop; ++y) {
for (x = 0; x < (hSize >> 2); ++x) {
*(pOut.word + x) = *(pIn.word + x);
}
pOut.pix += hdim;
}
// Repeat last line at the bottom
pIn.pix = out - hdim;
pOut.pix = out;
for (y = 0; y < repeatBot; ++y) {
for (x = 0; x < (hSize >> 2); ++x) {
*(pOut.word + x) = *(pIn.word + x);
}
pOut.pix += hdim;
}
return;
}
// mvDiff - Return YES if motion vector for adjacent block is different, otherwise NO
// Return NO if adjacent block is INTRA (unless PBframe)
static int mvDiff( int mvX, int mvY, // motion vector
MACROBLOCK_DESCR const *borderMB, // adjacent macroblock
int subBlk, // adjacent subblock (needed if borderMB has 4 motion vectors)
int PBframe, // If PBframe: do overlap also with INTRA neighbor
int border[2] // return motion vector components for adjacent block
)
{
if (borderMB->mtype == MTYPE263_INTER4V) {
border[0] = borderMB->blkMvX[ subBlk ];
border[1] = borderMB->blkMvY[ subBlk ];
} else {
border[0] = borderMB->mv_x;
border[1] = borderMB->mv_y;
if (borderMB->mtype >= MTYPE263_INTRA && PBframe == 0) {
return( NO ); // No overlap with INTRA neighbor (except in PBframe)
}
}
if (border[0] != mvX || border[1] != mvY) {
return( YES );
}
return( NO );
}
// median3 - return median of 3 values
static int median3( int x[3] )
{
int order[2];
if (x[1] < x[0]) {
order[0] = x[1];
order[1] = x[0];
} else {
order[0] = x[0];
order[1] = x[1];
}
if (x[2] < order[0]) {
return( order[0] );
} else if (x[2] < order[1]) {
return( x[2] );
}
return( order[1] );
}
// MvPred - Compute mv predictor (mvX,mvY) for block "blk" of macroblock mb[0].
// blk = UPPER_LEFT_BLK, UPPER_RIGHT_BLK, LOWER_LEFT_BLK, LOWER_RIGHT_BLK,
// or WHOLE_MACROBLOCK.
// If horPredOnly=YES: don't use previous row of macroblocks in prediction
extern void MvPred( MACROBLOCK_DESCR mb[],
int blk, // specify block: UL, UR, LL, LR, or WHOLE
int mbhor, // offset from previous row of MBs
int horPredOnly,
int *mvX, int *mvY )
{
int x[3], y[3];
switch (blk) {
case UPPER_RIGHT_BLK:
x[0] = mb[0].blkMvX[UPPER_LEFT_BLK];
y[0] = mb[0].blkMvY[UPPER_LEFT_BLK];
if (horPredOnly == YES) { // Top border or sending GOB header to resync
*mvX = x[0], *mvY = y[0];
} else {
if (mb[-mbhor].mtype == MTYPE263_INTER4V) {
x[1] = mb[-mbhor].blkMvX[LOWER_RIGHT_BLK];
y[1] = mb[-mbhor].blkMvY[LOWER_RIGHT_BLK];
} else {
x[1] = mb[-mbhor].mv_x;
y[1] = mb[-mbhor].mv_y;
}
if (mb[0].x == mbhor - 1) { // Right border
x[2] = 0, y[2] = 0;
} else if (mb[1-mbhor].mtype == MTYPE263_INTER4V) {
x[2] = mb[1-mbhor].blkMvX[LOWER_LEFT_BLK];
y[2] = mb[1-mbhor].blkMvY[LOWER_LEFT_BLK];
} else {
x[2] = mb[1-mbhor].mv_x;
y[2] = mb[1-mbhor].mv_y;
}
*mvX = median3( x );
*mvY = median3( y );
}
break;
case LOWER_LEFT_BLK:
if (mb[0].x == 0) { // Left border
x[0] = 0, y[0] = 0;
} else if (mb[-1].mtype == MTYPE263_INTER4V) {
x[0] = mb[-1].blkMvX[LOWER_RIGHT_BLK];
y[0] = mb[-1].blkMvY[LOWER_RIGHT_BLK];
} else {
x[0] = mb[-1].mv_x;
y[0] = mb[-1].mv_y;
}
x[1] = mb[0].blkMvX[UPPER_LEFT_BLK];
y[1] = mb[0].blkMvY[UPPER_LEFT_BLK];
x[2] = mb[0].blkMvX[UPPER_RIGHT_BLK];
y[2] = mb[0].blkMvY[UPPER_RIGHT_BLK];
*mvX = median3( x );
*mvY = median3( y );
break;
case LOWER_RIGHT_BLK:
x[0] = mb[0].blkMvX[LOWER_LEFT_BLK];
y[0] = mb[0].blkMvY[LOWER_LEFT_BLK];
x[1] = mb[0].blkMvX[UPPER_LEFT_BLK];
y[1] = mb[0].blkMvY[UPPER_LEFT_BLK];
x[2] = mb[0].blkMvX[UPPER_RIGHT_BLK];
y[2] = mb[0].blkMvY[UPPER_RIGHT_BLK];
*mvX = median3( x );
*mvY = median3( y );
break;
case WHOLE_MACROBLOCK:
case UPPER_LEFT_BLK:
default:
if (mb[0].x == 0) { // Left border
x[0] = 0, y[0] = 0;
} else if (mb[-1].mtype == MTYPE263_INTER4V) {
x[0] = mb[-1].blkMvX[UPPER_RIGHT_BLK];
y[0] = mb[-1].blkMvY[UPPER_RIGHT_BLK];
} else {
x[0] = mb[-1].mv_x;
y[0] = mb[-1].mv_y;
}
if (horPredOnly == YES) { // Top border or sending GOB header to resync
*mvX = x[0], *mvY = y[0];
} else {
if (mb[-mbhor].mtype == MTYPE263_INTER4V) {
x[1] = mb[-mbhor].blkMvX[LOWER_LEFT_BLK];
y[1] = mb[-mbhor].blkMvY[LOWER_LEFT_BLK];
} else {
x[1] = mb[-mbhor].mv_x;
y[1] = mb[-mbhor].mv_y;
}
if (mb[0].x == mbhor - 1) { // Right border
x[2] = 0, y[2] = 0;
} else if (mb[1-mbhor].mtype == MTYPE263_INTER4V) {
x[2] = mb[1-mbhor].blkMvX[LOWER_LEFT_BLK];
y[2] = mb[1-mbhor].blkMvY[LOWER_LEFT_BLK];
} else {
x[2] = mb[1-mbhor].mv_x;
y[2] = mb[1-mbhor].mv_y;
}
*mvX = median3( x );
*mvY = median3( y );
}
break;
}
return;
}
// doOverlapMC - Perform overlapped motion compensation on 8x8 block
static void doOverlapMC( int subBlk, // Indicates subblock to process (UL, UR, LL, LR)
MACROBLOCK_DESCR *mb, // Used to determine (x,y) coordinates for block
PICTURE *prevPic, // Previous picture; used to create overlapping MC
PICTURE *pic, // Contains non-overlapped MC on entry; returns overlapped MC
int borderMv[4][2], // Motion vectors for adjacent blocks (L,Top,R,Bottom)
int left, // If YES, overlap using LEFT mv
int top, // If YES, overlap using TOP mv
int right, // If YES, overlap using RIGHT mv
int bottom // If YES, overlap using BOTTOM mv
)
{
#define LEFT_ADDR (0)
#define RIGHT_ADDR (LEFT_ADDR + 4)
#define TOP_OFFSET (8)
#define TOP_ADDR (LEFT_ADDR + TOP_OFFSET)
#define MAX_HDIM (352)
static PIXEL p[8 * MAX_HDIM]; // MC predictions using neighboring vectors
// Only using first 16 columns; line offset chosen to be same as for pictures
int row, col, picOffset, hdim, nhor, nvert, *mv;
PIXEL * source, * dest;
void (*pMC) ( int hSize, int vSize, PIXEL *in, PIXEL *out, int hdim, int mvX, int mvY);
#if defined(COMPILE_MMX)
if(cpuid_is_mmx_motion_on()) {
//do mmx if compiler switch AND initialized AND detected
pMC = mcMMX;
} else
#endif
{
pMC = mc;
}
// Compute luma pointers
col = 16 * mb->x;
row = 16 * mb->y;
if (subBlk == UPPER_RIGHT_BLK || subBlk == LOWER_RIGHT_BLK) col += 8;
if (subBlk == LOWER_LEFT_BLK || subBlk == LOWER_RIGHT_BLK) row += 8;
hdim = pic->y.hoffset;
nhor = pic->y.nhor, nvert = pic->y.nvert;
picOffset = col + row * hdim;
dest = pic->y.ptr + picOffset; // Point to output luma (non-overlapped MC)
source = prevPic->y.ptr + picOffset; // Point to input luma (without motion comp)
if (hdim > MAX_HDIM) {
H261ErrMsg("doOverlapMC - Increase size of internal array");
exit(0);
}
// Create motion compensated blocks using neighboring motion vectors
if (left == YES) { // Produce left 4 columns
mv = borderMv[LEFT];
if (PointingOutside( col, col+3, row, row+7, *mv, *(mv+1), nhor, nvert) == NO) {
pMC( 4,8, source, &p[LEFT_ADDR], hdim, *mv, *(mv+1) );
} else {
limitMC( 4,8, source, &p[LEFT_ADDR], hdim, *mv, *(mv+1),
-col, nhor - 1 - col, -row, nvert - 1 - row );
}
}
if (right == YES) { // Produce right 4 columns
mv = borderMv[RIGHT];
if (PointingOutside( col+4, col+7, row, row+7, *mv, *(mv+1), nhor, nvert) == NO) {
pMC( 4,8, source + 4, &p[RIGHT_ADDR], hdim, *mv, *(mv+1) );
} else {
limitMC( 4,8, source + 4, &p[RIGHT_ADDR], hdim, *mv, *(mv+1),
-col - 4, nhor - 1 - col - 4, -row, nvert - 1 - row );
}
}
if (top == YES) { // Produce top 4 rows
mv = borderMv[TOP];
if (PointingOutside( col, col+7, row, row+3, *mv, *(mv+1), nhor, nvert) == NO) {
pMC( 8,4, source, &p[TOP_ADDR], hdim, *mv, *(mv+1) );
} else {
limitMC( 8,4, source, &p[TOP_ADDR], hdim, *mv, *(mv+1),
-col, nhor - 1 - col, -row, nvert - 1 - row );
}
}
if (bottom == YES) { // Produce bottom 4 rows
mv = borderMv[BOTTOM];
if (PointingOutside( col, col+7, row+4, row+7, *mv, *(mv+1), nhor, nvert) == NO) {
pMC( 8,4, source + 4*hdim, &p[TOP_ADDR + 4*hdim], hdim, *mv, *(mv+1) );
} else {
limitMC( 8,4, source + 4*hdim, &p[TOP_ADDR + 4*hdim], hdim, *mv, *(mv+1),
-col, nhor - 1 - col, -row - 4, nvert - 1 - row - 4 );
}
}
// Produce weighted ("overlapped") MC prediction
weigh8x4( dest, &p[LEFT_ADDR], hdim, top, left, right ); // Top 4 rows
weigh8x4( dest + 7*hdim, &p[LEFT_ADDR + 7*hdim], -hdim, bottom, left, right ); // Bottom 4 rows
return;
}
// weigh8x4
static void weigh8x4( PIXEL *dest, PIXEL const *p, int hdim, int vert, int left, int right )
{
if (vert == YES) { // Use top/bottom MV
if (left == YES) {
weighLeft_Vert( dest, &p[LEFT_ADDR], hdim );
} else {
weighNoLeft_Vert( dest, &p[LEFT_ADDR], hdim );
}
if (right == YES) {
weighRight_Vert( dest + 4, &p[RIGHT_ADDR], hdim );
} else {
weighNoRight_Vert( dest + 4, &p[RIGHT_ADDR], hdim );
}
} else {
if (left == YES) {
weighLeft( dest, &p[LEFT_ADDR], hdim );
}
if (right == YES) {
weighRight( dest + 4, &p[RIGHT_ADDR], hdim );
}
}
return;
}
// weighLeft_Vert - Overlap three MC predictions for upper left 4x4 pixels
static void weighLeft_Vert( PIXEL *dest, // Non-overlapped MC; overlapped by this routine
PIXEL const *p, // p: MC using left motion vector
// &p[TOP_OFFSET]: MC using top/bottom MV
int hdim ) // Line offset
{
// First row
dest[0] = (2 * dest[0] + p[0] + p[TOP_OFFSET + 0] + 2) >> 2;
dest[1] = (5 * dest[1] + p[1] + 2 * p[TOP_OFFSET + 1] + 4) >> 3;
dest[2] = (5 * dest[2] + p[2] + 2 * p[TOP_OFFSET + 2] + 4) >> 3;
dest[3] = (5 * dest[3] + p[3] + 2 * p[TOP_OFFSET + 3] + 4) >> 3;
// Second row
dest += hdim, p += hdim;
dest[0] = (5 * dest[0] + 2 * p[0] + p[TOP_OFFSET + 0] + 4) >> 3;
dest[1] = (5 * dest[1] + 2 * p[1] + p[TOP_OFFSET + 1] + 4) >> 3;
dest[2] = (5 * dest[2] + p[2] + 2 * p[TOP_OFFSET + 2] + 4) >> 3;
dest[3] = (5 * dest[3] + p[3] + 2 * p[TOP_OFFSET + 3] + 4) >> 3;
// Third row
dest += hdim, p += hdim;
dest[0] = (5 * dest[0] + 2 * p[0] + p[TOP_OFFSET + 0] + 4) >> 3;
dest[1] = (5 * dest[1] + 2 * p[1] + p[TOP_OFFSET + 1] + 4) >> 3;
dest[2] = (6 * dest[2] + p[2] + p[TOP_OFFSET + 2] + 4) >> 3;
dest[3] = (6 * dest[3] + p[3] + p[TOP_OFFSET + 3] + 4) >> 3;
// Fourth row (identical to third row)
dest += hdim, p += hdim;
dest[0] = (5 * dest[0] + 2 * p[0] + p[TOP_OFFSET + 0] + 4) >> 3;
dest[1] = (5 * dest[1] + 2 * p[1] + p[TOP_OFFSET + 1] + 4) >> 3;
dest[2] = (6 * dest[2] + p[2] + p[TOP_OFFSET + 2] + 4) >> 3;
dest[3] = (6 * dest[3] + p[3] + p[TOP_OFFSET + 3] + 4) >> 3;
return;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?