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 + -
显示快捷键?