📄 mcomp.c
字号:
/* ***** 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 functionsstatic 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.261extern 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++) { 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -