mcomp.c

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

C
1,603
字号
/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: mcomp.c,v 1.2.42.1 2004/07/09 01:56:22 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

/*-----------------------------------------------------------------------------
 *  MCOMP.C
 *
 *  DESCRIPTION
 *      mcomp.c - Motion compensation for H.263 codec
 *          Performs motion compensation for a macroblock with half-pixel accuracy
 *          Supports Unrestricted Motion Vector mode, i.e., motion vectors are allowed
 *          to point outside picture boundaries; uses edge pixels when needed.
 *          Supports Advanced Prediction mode, i.e., four motion vectors per macroblock
 *          and overlapped motion compensation for luminance.
 *
 *          In Advanced Prediction mode, the prediction is formed in two steps.
 *          First, MotionComp263 is called to generate non-overlapped motion compensation.
 *          Then, OverlapMC is called to perform the overlapping on the luminance.
 *          OverlapMC requires mv's from left, top, and right neighbors.  Therefore,
 *          the encoder needs to decide on the coding mode for the next mb (i.e., to the
 *          right) before overlap can be done.
 *
 *          In PB-frame mode, the B-frame prediction is generated by PredBframe.  It uses
 *          previous P-frame and the corresponding macroblock from the next P-frame.
 *          Hence, the next P-frame macroblock needs to be reconstructed before calling 
 *          PredBframe.
 *
 *          This module also contains the motion compensation routine for 
 *          H.261 (MotionComp), which performs integer motion compensation.
 *          MotionComp was extracted from file PREDSEL.C and modified.
 *
 *  CALLING SEQUENCE
 *      MotionComp263(  MACROBLOCK_DESCR * mb,  // Describes block to be motion-compensated
 *                      PICTURE * prev_pic,     // Describes previous picture used to form MC
 *                      PICTURE * pic)          // Output picture where MC block is placed
 *      OverlapMC( 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     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
 *      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
 *                      )
 *
 *          The routines do not return a value.
 *
 *          Assumptions:
 *          1. "pic", "prev_pic", "nextPic", and "Bpic" have same line offset and size
 *          2. Chroma components Cb and Cr have same line offset and size
 *          3. All arrays are quad-aligned, i.e., start address is multiple of 4.
 *          4. Motion vectors are represented with one fractional bit
 *
 *
 *      MotionComp(     MACROBLOCK_DESCR * mb,  // Describes block to be motion-compensated
 *                      PICTURE * prev_pic,     // Describes previous picture used to form MC
 *                      PICTURE * pic )         // Output picture where MC block is placed
 *
 *          The routine returns H261_ERROR if motion vectors point outside picture, otherwise OK.
 *
 *          Assumptions:
 *          1-3. As above
 *          4. Motion vectors are represented by integers.
 *
 *
 -----------------------------------------------------------------------------*/ 

//#include <stdio.h>
//#include <stdlib.h>
#ifdef _MACINTOSH
#include <stdlib.h> // for exit()
#endif
#include "dllindex.h"
#include "h261defs.h"
#include "h261func.h"


#ifdef COMPILE_MMX
#include "mmxcpuid.h"
#endif

//#define VVPROFILER
#ifdef VVPROFILER
#include "hvdebtim.h"
extern struct CVvDebugTimer * pVvProf[];
extern unsigned long			pVvProfCount[];
#endif

// Declarations of local functions
static int chromaMVComp( int mvLuma );
static int chromaMvComp4V( S8 mvLuma[4] );
void mc( int hSize, int vSize, 
                    PIXEL in[], PIXEL out[], int hdim,
                    int mvX, int mvY    // Motion vector
                    );
void mcMMX( int hSize, int vSize, 
                    PIXEL in[], PIXEL out[], int hdim,
                    int mvX, int mvY    // Motion vector
                    );
static void limitMC( int hSize, int vSize, 
                    PIXEL const *in, PIXEL *out, int hdim,
                    int mvX, int mvY,   // Motion vector
                    int minX, int maxX, int minY, int maxY // Limits for hor/vert indices
                    );
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
                );
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
                    );
static void weigh8x4( PIXEL dest[], PIXEL const *p, int hdim, int vert, int left, int right );
static void weighLeft_Vert( PIXEL *dest, PIXEL const *p, int hdim );
static void weighNoLeft_Vert( PIXEL *dest, PIXEL const *p, int hdim );
static void weighLeft( PIXEL *dest, PIXEL const *p, int hdim );
static void weighRight_Vert( PIXEL *dest, PIXEL const *p, int hdim );
static void weighNoRight_Vert( PIXEL *dest, PIXEL const *p, int hdim );
static void weighRight( PIXEL *dest, PIXEL const *p, int hdim );
static void mc16pelsNoInterpol( PIXEL *in, PIXEL out[], int hdim, int vSize );
static void mc8pelsNoInterpol( PIXEL *in, PIXEL out[], int hdim, int vSize );
static void mc4pelsNoInterpol( PIXEL *in, PIXEL out[], int hdim, int vSize );
static void mc16pelsHorInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc8pelsHorInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc4pelsHorInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc16pelsVertInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc8pelsVertInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc4pelsVertInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc16pels2DInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc8pels2DInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void mc4pels2DInterpol( PIXEL const *in, PIXEL out[], int hdim, int vSize );
static void saveBackwardPred( MACROBLOCK_DESCR * mb,    // Describes block to be saved
                              PICTURE * pic // Picture with pixels to be saved
                              );
static void averageForBack( MACROBLOCK_DESCR * mb,  // Describes block to be averaged
                            PICTURE * pic   // Input: contains forward prediction
                                            // Output: contains B-frame prediction
                            );
static void copyBlock( S32 source[], int hSize, int vSize, int sourceOffset,
                       S32 dest[], int destOffset );
void averageBlock( PIXEL forPred[], int hSize, int vSize, int forOffset,
                          PIXEL backPred[], int backOffset );
void averageBlockMMX( PIXEL forPred[], int hSize, int vSize, int forOffset,
                          PIXEL backPred[], int backOffset );


// MotionComp - perform integer-pixel motion compensation for H.261
extern int  MotionComp( MACROBLOCK_DESCR *mb, PICTURE *prev_pic, PICTURE *pic )
{
    int     row, col, status, i, cx, cy, pic_offset, prev_offset;
    union {     // Copy words to speed up routine
        PIXEL   * pix;
        S32    * word;
    } pixel, prev;
    PIXEL   * source, * dest;

    status = OK;
    if (mb->mv_x == 0  &&  mb->mv_y == 0) {   // Copy macroblock
        col = 16 * mb->x;
        row = 16 * mb->y;
        pic_offset = col + row * pic->y.hoffset;
        pixel.pix = pic->y.ptr + pic_offset;
        prev.pix = prev_pic->y.ptr + pic_offset;
        for (i = 0; i < 16; i++) {
            *(pixel.word) = *(prev.word);
            *(pixel.word + 1) = *(prev.word + 1);
            *(pixel.word + 2) = *(prev.word + 2);
            *(pixel.word + 3) = *(prev.word + 3);
            pixel.pix += pic->y.hoffset;
            prev.pix += pic->y.hoffset;
        }
        if (pic->color) {
            col = 8 * mb->x;
            row = 8 * mb->y;
            // Assuming same offset for Cr and Cb
            pic_offset = col + row * pic->cb.hoffset;
            pixel.pix = pic->cb.ptr + pic_offset;
            prev.pix = prev_pic->cb.ptr + pic_offset;
            for (i = 0; i < 8; i++) {
                *(pixel.word) = *(prev.word);
                *(pixel.word + 1) = *(prev.word + 1);
                pixel.pix += pic->cb.hoffset;
                prev.pix += pic->cb.hoffset;
            }
            pixel.pix = pic->cr.ptr + pic_offset;
            prev.pix = prev_pic->cr.ptr + pic_offset;
            for (i = 0; i < 8; i++) {
                *(pixel.word) = *(prev.word);
                *(pixel.word + 1) = *(prev.word + 1);
                pixel.pix += pic->cr.hoffset;
                prev.pix += pic->cr.hoffset;
            }
        }
    } else {    // Non-zero motion vector
        // Wrap motion vectors to allowed range
        while (mb->mv_x < MV_MIN) {
            mb->mv_x += MV_WRAP;
        }
        while (mb->mv_x > MV_MAX) {
            mb->mv_x -= MV_WRAP;
        }
        while (mb->mv_y < MV_MIN) {
            mb->mv_y += MV_WRAP;
        }
        while (mb->mv_y > MV_MAX) {
            mb->mv_y -= MV_WRAP;
        }
        // Compute pointers
        col = 16 * mb->x;
        row = 16 * mb->y;
        if (col == 0  &&  mb->mv_x < 0) {    // Pointing left of first col?
            mb->mv_x = 0, status = H261_ERROR;
        }
        if (col == pic->y.nhor - 16  &&  mb->mv_x > 0) {  // Right of last col?
            mb->mv_x = 0, status = H261_ERROR;
        }
        if (row == 0  &&  mb->mv_y < 0) {    // Pointing above first row?
            mb->mv_y = 0, status = H261_ERROR;
        }
        if (row == pic->y.nvert - 16  &&  mb->mv_y > 0) {  // Below last row?
            mb->mv_y = 0, status = H261_ERROR;
        }
        // Copy displaced macroblock
        pic_offset = col + row * pic->y.hoffset;
        prev_offset = col + mb->mv_x + (row + mb->mv_y) * pic->y.hoffset;
        pixel.pix = pic->y.ptr + pic_offset;
        prev.pix = prev_pic->y.ptr + prev_offset;
        for (i = 0; i < 16; i++) {
            source = prev.pix;
            for (dest = pixel.pix; dest < pixel.pix + 16; dest++) {
                *dest = *(source++);
            }
            pixel.pix += pic->y.hoffset;
            prev.pix += pic->y.hoffset;
        }
        if (pic->color) {
            col = 8 * mb->x;
            row = 8 * mb->y;
            // Truncate motion vectors for chroma towards zero
            if (mb->mv_x < 0) {
                cx = (mb->mv_x + 1) >> 1;
            } else {
                cx = mb->mv_x >> 1;
            }
            if (mb->mv_y < 0) {
                cy = (mb->mv_y + 1) >> 1;
            } else {
                cy = mb->mv_y >> 1;
            }
            // Assuming same offset for Cr and Cb
            pic_offset = col + row * pic->cb.hoffset;
            prev_offset = col + cx + (row + cy) * pic->cb.hoffset;
            pixel.pix = pic->cb.ptr + pic_offset;
            prev.pix = prev_pic->cb.ptr + prev_offset;
            for (i = 0; i < 8; i++) {
                source = prev.pix;
                for (dest = pixel.pix; dest < pixel.pix + 8; dest++) {
                    *dest = *(source++);
                }
                pixel.pix += pic->cb.hoffset;
                prev.pix += pic->cb.hoffset;
            }
            pixel.pix = pic->cr.ptr + pic_offset;
            prev.pix = prev_pic->cr.ptr + prev_offset;
            for (i = 0; i < 8; i++) {

⌨️ 快捷键说明

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