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