mcomp.c

来自「symbian 下的helix player源代码」· C语言 代码 · 共 1,603 行 · 第 1/5 页

C
1,603
字号
                source = prev.pix;
                for (dest = pixel.pix; dest < pixel.pix + 8; dest++) {
                    *dest = *(source++);
                }
                pixel.pix += pic->cr.hoffset;
                prev.pix += pic->cr.hoffset;
            }
        }
    }
    return (status);
}



// MotionComp263 - perform half-pixel motion compensation for H.263
extern void MotionComp263( MACROBLOCK_DESCR * mb, // Describes block to be motion-compensated
                            PICTURE * prevPic,  // Describes previous picture used to form MC
                            PICTURE * pic       // Output picture where MC block is placed
                            )
{
    int     row, col, cX, cY, picOffset, hdim, nhor, nvert;
    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;
    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
    source = prevPic->y.ptr + picOffset;    // Point to input luma (without motion comp)
    // Do motion compensation for luma
    if (mb->mtype == MTYPE263_INTER4V) {    // 4 motion vectors
        // Upper left block
        if (PointingOutside( col, col+7, row, row+7, mb->blkMvX[UPPER_LEFT_BLK], 
                            mb->blkMvY[UPPER_LEFT_BLK], nhor, nvert )  ==  NO) {
            pMC( 8, 8, source, dest, hdim, 
                        mb->blkMvX[UPPER_LEFT_BLK], mb->blkMvY[UPPER_LEFT_BLK] );
        } else {
            limitMC( 8, 8, source, dest, hdim,
                        mb->blkMvX[UPPER_LEFT_BLK], mb->blkMvY[UPPER_LEFT_BLK],
                        -col, nhor - 1 - col, -row, nvert - 1 - row );
        }
        // Upper right block
        if (PointingOutside( col+8, col+15, row, row+7, mb->blkMvX[UPPER_RIGHT_BLK], 
                            mb->blkMvY[UPPER_RIGHT_BLK], nhor, nvert )  ==  NO) {
            pMC( 8, 8, source + 8, dest + 8, hdim,
                        mb->blkMvX[UPPER_RIGHT_BLK], mb->blkMvY[UPPER_RIGHT_BLK] );
        } else {
            limitMC( 8, 8, source + 8, dest + 8, hdim,
                        mb->blkMvX[UPPER_RIGHT_BLK], mb->blkMvY[UPPER_RIGHT_BLK],
                        -col - 8, nhor - 1 - col - 8, -row, nvert - 1 - row );
        }
        // Lower left block
        source += 8 * hdim;   // Advance 8 lines
        dest += 8 * hdim;
        if (PointingOutside( col, col+7, row+8, row+15, mb->blkMvX[LOWER_LEFT_BLK], 
                            mb->blkMvY[LOWER_LEFT_BLK], nhor, nvert )  ==  NO) {
            pMC( 8, 8, source, dest, hdim,
                        mb->blkMvX[LOWER_LEFT_BLK], mb->blkMvY[LOWER_LEFT_BLK] );
        } else {
            limitMC( 8, 8, source, dest, hdim,
                        mb->blkMvX[LOWER_LEFT_BLK], mb->blkMvY[LOWER_LEFT_BLK],
                        -col, nhor - 1 - col, -row - 8, nvert - 1 - row - 8 );
        }
        // Lower right block
        if (PointingOutside( col+8, col+15, row+8, row+15, mb->blkMvX[LOWER_RIGHT_BLK],
                            mb->blkMvY[LOWER_RIGHT_BLK], nhor, nvert )  ==  NO) {
            pMC( 8, 8, source + 8, dest + 8, hdim,
                        mb->blkMvX[LOWER_RIGHT_BLK], mb->blkMvY[LOWER_RIGHT_BLK] );
        } else {
            limitMC( 8, 8, source + 8, dest + 8, hdim,
                        mb->blkMvX[LOWER_RIGHT_BLK], mb->blkMvY[LOWER_RIGHT_BLK],
                        -col - 8, nhor - 1 - col - 8, -row - 8, nvert - 1 - row - 8 );
        }
        // Compute chroma mv
        cX = chromaMvComp4V( mb->blkMvX );
        cY = chromaMvComp4V( mb->blkMvY );
    
    } else {    // One motion vector
        if (PointingOutside( col, col+15, row, row+15, mb->mv_x, mb->mv_y,
                                nhor, nvert )  ==  NO) {
            pMC( 16, 16, source, dest, hdim, mb->mv_x, mb->mv_y );
        } else {    // Pointing outside
            limitMC( 16, 16, source, dest, hdim, mb->mv_x, mb->mv_y,
                        -col, nhor - 1 - col, -row, nvert - 1 - row );
        }
        // Compute chroma mv
        cX = chromaMVComp( mb->mv_x );
        cY = chromaMVComp( mb->mv_y );
    }
    
    // Do motion compensation for chroma
    if (pic->color) {
        // Compute chroma pointers
        col = 8 * mb->x;
        row = 8 * mb->y;
        hdim = pic->cb.hoffset;
        nhor = pic->cb.nhor, nvert = pic->cb.nvert;
        picOffset = col + row * hdim;
        if (PointingOutside( col, col+7, row, row+7, cX, cY, nhor, nvert )  ==  NO) {
            pMC( 8, 8, prevPic->cb.ptr + picOffset, pic->cb.ptr + picOffset, hdim, cX, cY );
            pMC( 8, 8, prevPic->cr.ptr + picOffset, pic->cr.ptr + picOffset, hdim, cX, cY );
        } else {
            limitMC( 8, 8, prevPic->cb.ptr + picOffset, pic->cb.ptr + picOffset,
                    hdim, cX, cY, -col, nhor - 1 - col, -row, nvert - 1 - row );
            limitMC( 8, 8, prevPic->cr.ptr + picOffset, pic->cr.ptr + picOffset,
                    hdim, cX, cY, -col, nhor - 1 - col, -row, nvert - 1 - row );
        }
    }
    return;
}


// printBlk - for debugging
/*static void printBlk( int hSize, int vSize, PIXEL *p, int hdim)
{
    int i,j;
    
    for (i = 0; i < vSize; ++i) {
        for (j = 0; j < hSize; ++j) {
            printf(" %3d", *(p + j));
        }
        printf("\n");
        p += hdim;
    }
    return;
}*/


// Enumerate array of motion vectors
#define LEFT        (0)
#define TOP         (1)
#define RIGHT       (2)
#define BOTTOM      (3)

// Do overlapped motion comp. for luma
extern void OverlapMC( MACROBLOCK_DESCR * mb,   // Describes block to be motion-compensated
                        int     PBframe,    // Non-zero if PB frame
                        PICTURE * prevPic,  // Describes previous picture used to form MC
                        PICTURE * pic,      // Output picture where MC block is placed
                        int     mbWidth,    // Macroblocks per row
                        int     mbOffset,   // Row offset; (mb-mbOffset) is neighbor on top
                        int     overlap[4]  // Returns YES or NO to indicate whether overlap
                                            // was done in each 8x8 subblock
                        )
{
    int left, top, right, bottom, mvX, mvY;
    int borderMv[4][2]; // motion vectors for neighbors (left, top, right, bottom)
    
    if (mb->mtype == MTYPE263_INTER4V) {
        // Upper left block
        mvX = mb->blkMvX[UPPER_LEFT_BLK];
        mvY = mb->blkMvY[UPPER_LEFT_BLK];
        if (mb->x == 0)  left = NO;
        else  left = mvDiff( mvX, mvY, mb-1, UPPER_RIGHT_BLK, PBframe, borderMv[LEFT] );
        if (mb->y == 0)  top = NO;
        else  top = mvDiff( mvX, mvY, mb-mbOffset, LOWER_LEFT_BLK, PBframe, borderMv[TOP] );
        right = mvDiff( mvX, mvY, mb, UPPER_RIGHT_BLK, PBframe, borderMv[RIGHT] );
        bottom = mvDiff( mvX, mvY, mb, LOWER_LEFT_BLK, PBframe, borderMv[BOTTOM] );
        if (left == YES || right == YES || top == YES || bottom == YES) {
            doOverlapMC( UPPER_LEFT_BLK, mb, prevPic, pic, borderMv, left,top,right,bottom);
            overlap[UPPER_LEFT_BLK] = YES;
        } else {
            overlap[UPPER_LEFT_BLK] = NO;
        }
        // Upper right block
        mvX = mb->blkMvX[UPPER_RIGHT_BLK];
        mvY = mb->blkMvY[UPPER_RIGHT_BLK];
        left = mvDiff( mvX, mvY, mb, UPPER_LEFT_BLK, PBframe, borderMv[LEFT] );
        if (mb->y == 0)  top = NO;
        else  top = mvDiff( mvX, mvY, mb-mbOffset, LOWER_RIGHT_BLK, PBframe, borderMv[TOP] );
        if (mb->x == mbWidth-1)  right = NO;
        else  right = mvDiff( mvX, mvY, mb+1, UPPER_LEFT_BLK, PBframe, borderMv[RIGHT] );
        bottom = mvDiff( mvX, mvY, mb, LOWER_RIGHT_BLK, PBframe, borderMv[BOTTOM] );
        if (left == YES || right == YES || top == YES || bottom == YES) {
            doOverlapMC( UPPER_RIGHT_BLK, mb, prevPic, pic, borderMv, left,top,right,bottom);
            overlap[UPPER_RIGHT_BLK] = YES;
        } else {
            overlap[UPPER_RIGHT_BLK] = NO;
        }
        // Lower left block
        mvX = mb->blkMvX[LOWER_LEFT_BLK];
        mvY = mb->blkMvY[LOWER_LEFT_BLK];
        if (mb->x == 0)  left = NO;
        else  left = mvDiff( mvX, mvY, mb-1, LOWER_RIGHT_BLK, PBframe, borderMv[LEFT] );
        top = mvDiff( mvX, mvY, mb, UPPER_LEFT_BLK, PBframe, borderMv[TOP] );
        right = mvDiff( mvX, mvY, mb, LOWER_RIGHT_BLK, PBframe, borderMv[RIGHT] );
        if (left == YES || right == YES || top == YES) {
            doOverlapMC( LOWER_LEFT_BLK, mb, prevPic, pic, borderMv, left,top,right,NO);
            overlap[LOWER_LEFT_BLK] = YES;
        } else {
            overlap[LOWER_LEFT_BLK] = NO;
        }
        // Lower right block
        mvX = mb->blkMvX[LOWER_RIGHT_BLK];
        mvY = mb->blkMvY[LOWER_RIGHT_BLK];
        left = mvDiff( mvX, mvY, mb, LOWER_LEFT_BLK, PBframe, borderMv[LEFT] );
        top = mvDiff( mvX, mvY, mb, UPPER_RIGHT_BLK, PBframe, borderMv[TOP] );
        if (mb->x == mbWidth-1)  right = NO;
        else  right = mvDiff( mvX, mvY, mb+1, LOWER_LEFT_BLK, PBframe, borderMv[RIGHT] );
        if (left == YES || right == YES || top == YES) {
            doOverlapMC( LOWER_RIGHT_BLK, mb, prevPic, pic, borderMv, left,top,right,NO);
            overlap[LOWER_RIGHT_BLK] = YES;
        } else {
            overlap[LOWER_RIGHT_BLK] = NO;
        }
        
    } else {    // One motion vector for current macroblock; neighbors can be INTER4V
        mvX = mb->mv_x;
        mvY = mb->mv_y;
        // Upper left block
        if (mb->x == 0)  left = NO;
        else  left = mvDiff( mvX, mvY, mb-1, UPPER_RIGHT_BLK, PBframe, borderMv[LEFT] );
        if (mb->y == 0)  top = NO;
        else  top = mvDiff( mvX, mvY, mb-mbOffset, LOWER_LEFT_BLK, PBframe, borderMv[TOP] );
        if (left == YES || top == YES) {
            doOverlapMC( UPPER_LEFT_BLK, mb, prevPic, pic, borderMv, left,top,NO,NO);
            overlap[UPPER_LEFT_BLK] = YES;
        } else {
            overlap[UPPER_LEFT_BLK] = NO;
        }
        // Upper right block
        if (mb->y == 0)  top = NO;
        else  top = mvDiff( mvX, mvY, mb-mbOffset, LOWER_RIGHT_BLK, PBframe, borderMv[TOP] );
        if (mb->x == mbWidth-1)  right = NO;
        else  right = mvDiff( mvX, mvY, mb+1, UPPER_LEFT_BLK, PBframe, borderMv[RIGHT] );
        if (right == YES || top == YES) {
            doOverlapMC( UPPER_RIGHT_BLK, mb, prevPic, pic, borderMv, NO,top,right,NO);
            overlap[UPPER_RIGHT_BLK] = YES;
        } else {
            overlap[UPPER_RIGHT_BLK] = NO;
        }
        // Lower left block
        if (mb->x == 0)  left = NO;
        else  left = mvDiff( mvX, mvY, mb-1, LOWER_RIGHT_BLK, PBframe, borderMv[LEFT] );
        if (left == YES) {
            doOverlapMC( LOWER_LEFT_BLK, mb, prevPic, pic, borderMv, left,NO,NO,NO);
            overlap[LOWER_LEFT_BLK] = YES;
        } else {
            overlap[LOWER_LEFT_BLK] = NO;
        }
        // Lower right block
        if (mb->x == mbWidth-1)  right = NO;
        else  right = mvDiff( mvX, mvY, mb+1, LOWER_LEFT_BLK, PBframe, borderMv[RIGHT] );
        if (right == YES) {
            doOverlapMC( LOWER_RIGHT_BLK, mb, prevPic, pic, borderMv, NO,NO,right,NO);
            overlap[LOWER_RIGHT_BLK] = YES;
        } else {
            overlap[LOWER_RIGHT_BLK] = NO;
        }
    }
    return;
}


// PointingOutside - determine whether motion-comp routine needs to worry about 
//  the borders of the previous picture (use edge pixels instead of non-existent
//  pixels "outside" the border of the previous picture).
//  Returns YES if the motion-compensated block needs pixels outside the previous
//  picture; NO if picture boundary is not crossed.
extern int PointingOutside( int col1, int col2, // First and last column of block
                            int row1, int row2, // First and last row of block
                            int mvX, int mvY,   // Motion vector; one fractional bit
                            int nCols, int nRows    // Picture size
                            )
{
    if (col1 + (mvX >> 1)  <  0)            // Check left border
        return( YES );
    if (col2 + ((mvX + 1) >> 1)  >=  nCols) // Check right border
        return( YES );
    if (row1 + (mvY >> 1)  <  0)            // Check top border
        return( YES );
    if (row2 + ((mvY + 1) >> 1)  >=  nRows) // Check bottom border
        return( YES );
    return( NO );
}


//  PredBframe - Form prediction for B-frame
extern void PredBframe( MACROBLOCK_DESCR * mb,  // Macroblock to be predicted
                        PICTURE * prevPic,      // Prev. picture (forward pred)
                        PICTURE * nextPic,      // Next P-picture (backward pred)
                        PICTURE * Bpic          // Output picture where pred is placed
                        )
{
    int     i;
    S8      saveMvX[4], saveMvY[4];

    // Perform backward prediction
    if (mb->mtype == MTYPE263_INTER4V) {
        for (i = 0; i < 4; ++i) {
            saveMvX[i] = mb->blkMvX[i];
            mb->blkMvX[i] = mb->blkMvBx[i];
            saveMvY[i] = mb->blkMvY[i];
            mb->blkMvY[i] = mb->blkMvBy[i];
        }
    } else {
        saveMvX[0] = mb->mv_x;
        mb->mv_x = mb->blkMvBx[0];
        saveMvY[0] = mb->mv_y;
        mb->mv_y = mb->blkMvBy[0];
    }
    MotionComp263( mb, nextPic, Bpic );
    // Save backward prediction in temporary area
    saveBackwardPred( mb, Bpic );
    // Perform forward prediction
    if (mb->mtype == MTYPE263_INTER4V) {
        for (i = 0; i < 4; ++i) {
            mb->blkMvX[i] = mb->blkMvFx[i];
            mb->blkMvY[i] = mb->blkMvFy[i];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?