📄 mc.cpp
字号:
/*************************************************************************
This software module was originally developed by
Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation
Bruce Lin (blin@microsoft.com), Microsoft Corporation
Simon Winder (swinder@microsoft.com), Microsoft Corporation
(date: June, 1997)
and edited by
Wei Wu (weiwu@stallion.risc.rockwell.com) Rockwell Science Center
in the course of development of the MPEG-4 Video (ISO/IEC 14496-2).
This software module is an implementation of a part of one or more MPEG-4 Video tools
as specified by the MPEG-4 Video.
ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications
thereof for use in hardware or software products claiming conformance to the MPEG-4 Video.
Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents.
The original developer of this software module and his/her company,
the subsequent editors and their companies,
and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation.
Copyright is not released for non MPEG-4 Video conforming products.
Microsoft retains full right to use the code for his/her own purpose,
assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products.
This copyright notice must be included in all copies or derivative works.
Copyright (c) 1996, 1997.
Module Name:
mc.cpp
Abstract:
Motion compensation routines (common for encoder and decoder).
Revision History:
December 20, 1997 Interlaced tools added by NextLevel Systems (GI)
X. Chen (xchen@nlvl.com) B. Eifrig (beifrig@nlvl.com)
`
*************************************************************************/
#include <stdio.h>
#include "typeapi.h"
#include "codehead.h"
#include "mode.hpp"
#include "vopses.hpp"
#include "global.hpp"
#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
#endif // __MFC_
Void CVideoObject::limitMVRangeToExtendedBBFullPel (CoordI &x,CoordI &y,CRct *prct,Int iBlkSize)
{
if(prct==NULL)
return;
if(x < prct->left)
x=prct->left;
else if(x > (prct->right-iBlkSize))
x=(prct->right-iBlkSize);
if(y < prct->top)
y=prct->top;
else if(y > (prct->bottom-iBlkSize))
y=(prct->bottom-iBlkSize);
}
Void CVideoObject::limitMVRangeToExtendedBBHalfPel (CoordI &x,CoordI &y,CRct *prct,Int iBlkSize)
{
if(prct==NULL)
return;
if(x < prct->left*2)
x=prct->left*2;
else if(x > (prct->right-iBlkSize)*2)
x=(prct->right-iBlkSize)*2;
if(y < prct->top*2)
y=prct->top*2;
else if(y > (prct->bottom-iBlkSize)*2)
y=(prct->bottom-iBlkSize)*2;
}
Void CVideoObject::motionCompMB (
PixelC* ppxlcPredMB,
const PixelC* ppxlcRefLeftTop,
const CMotionVector* pmv, const CMBMode* pmbmd,
Int imbX, Int imbY,
CoordI x, CoordI y,
Bool bSkipNonOBMC,
Bool bAlphaMB,
CRct *prctMVLimit
)
{
if (!bAlphaMB && !m_volmd.bAdvPredDisable && !pmbmd->m_bFieldMV) {
motionCompOverLap (
ppxlcPredMB, ppxlcRefLeftTop,
pmv, pmbmd,
imbX, imbY,
x, y,
prctMVLimit
);
}
else {
if (bSkipNonOBMC)
return;
if (!pmbmd -> m_bhas4MVForward && !pmbmd -> m_bFieldMV)
motionComp (
ppxlcPredMB, ppxlcRefLeftTop,
MB_SIZE,
x * 2 + pmv->trueMVHalfPel ().x,
y * 2 + pmv->trueMVHalfPel ().y ,
m_vopmd.iRoundingControl,
prctMVLimit
);
else if (pmbmd -> m_bFieldMV) {
const CMotionVector* pmv16x8 = pmv+5;
if(pmbmd->m_bForwardTop) {
pmv16x8++;
motionCompYField (
ppxlcPredMB,
ppxlcRefLeftTop+m_iFrameWidthY,
x * 2 + pmv16x8->trueMVHalfPel ().x,
y * 2 + pmv16x8->trueMVHalfPel ().y
);
pmv16x8++;
}
else {
motionCompYField (
ppxlcPredMB,
ppxlcRefLeftTop,
x * 2 + pmv16x8->trueMVHalfPel ().x,
y * 2 + pmv16x8->trueMVHalfPel ().y
);
pmv16x8++;
pmv16x8++;
}
if(pmbmd->m_bForwardBottom) {
pmv16x8++;
motionCompYField (
ppxlcPredMB+MB_SIZE,
ppxlcRefLeftTop+m_iFrameWidthY,
x * 2 + pmv16x8->trueMVHalfPel ().x,
y * 2 + pmv16x8->trueMVHalfPel ().y
);
}
else {
motionCompYField (
ppxlcPredMB+MB_SIZE,
ppxlcRefLeftTop,
x * 2 + pmv16x8->trueMVHalfPel ().x,
y * 2 + pmv16x8->trueMVHalfPel ().y
);
}
}
else {
const CMotionVector* pmv8 = pmv;
pmv8++;
CoordI blkX = x + BLOCK_SIZE;
CoordI blkY = y + BLOCK_SIZE;
if (pmbmd->m_rgTranspStatus [Y_BLOCK1] != ALL)
motionComp (
ppxlcPredMB, ppxlcRefLeftTop,
BLOCK_SIZE,
x * 2 + pmv8->trueMVHalfPel ().x,
y * 2 + pmv8->trueMVHalfPel ().y,
m_vopmd.iRoundingControl,
prctMVLimit
);
pmv8++;
if (pmbmd->m_rgTranspStatus [Y_BLOCK2] != ALL)
motionComp (
ppxlcPredMB + OFFSET_BLK1, ppxlcRefLeftTop,
BLOCK_SIZE,
blkX * 2 + pmv8->trueMVHalfPel ().x,
y * 2 + pmv8->trueMVHalfPel ().y,
m_vopmd.iRoundingControl,
prctMVLimit
);
pmv8++;
if (pmbmd->m_rgTranspStatus [Y_BLOCK3] != ALL)
motionComp (
ppxlcPredMB + OFFSET_BLK2, ppxlcRefLeftTop,
BLOCK_SIZE,
x * 2 + pmv8->trueMVHalfPel ().x,
blkY * 2 + pmv8->trueMVHalfPel ().y,
m_vopmd.iRoundingControl,
prctMVLimit
);
pmv8++;
if (pmbmd->m_rgTranspStatus [Y_BLOCK4] != ALL)
motionComp (
ppxlcPredMB + OFFSET_BLK3, ppxlcRefLeftTop,
BLOCK_SIZE,
blkX * 2 + pmv8->trueMVHalfPel ().x,
blkY * 2 + pmv8->trueMVHalfPel ().y,
m_vopmd.iRoundingControl,
prctMVLimit
);
}
}
}
Void CVideoObject::motionComp (
PixelC* ppxlcPred, // can be either Y or A
const PixelC* ppxlcRefLeftTop, // point to left-top of the frame
Int iSize, // either MB or BLOCK size
CoordI xRef, CoordI yRef, // x + mvX, in half pel unit
Int iRoundingControl,
CRct *prctMVLimit // extended bounding box
)
{
CoordI ix, iy;
limitMVRangeToExtendedBBHalfPel(xRef,yRef,prctMVLimit,iSize);
const PixelC* ppxlcRef =
ppxlcRefLeftTop +
((yRef >> 1) + EXPANDY_REF_FRAME) * m_iFrameWidthY + (xRef >> 1) + EXPANDY_REF_FRAME;
if(iSize==8 || iSize==16)
{
// optimisation
if (!(yRef & 1)) {
if (!(xRef & 1)) {
Int iSz = iSize * sizeof(PixelC);
for(iy = 0; iy < iSize; iy+=8)
{
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
memcpy (ppxlcPred, ppxlcRef, iSz);
ppxlcRef += m_iFrameWidthY; ppxlcPred += MB_SIZE;
}
}
else {
PixelC pxlcT1,pxlcT2, *ppxlcDst;
const PixelC *ppxlcSrc;
Int iRndCtrl = 1 - iRoundingControl;
for (iy = 0; iy < iSize; iy++){
ppxlcDst = ppxlcPred;
ppxlcSrc = ppxlcRef;
for (ix = 0; ix < iSize; ix+=8) {
ppxlcDst [0] = (ppxlcSrc[0] + (pxlcT1=ppxlcSrc[1]) + iRndCtrl) >> 1;
ppxlcDst [1] = (pxlcT1 + (pxlcT2=ppxlcSrc[2]) + iRndCtrl) >> 1;
ppxlcDst [2] = (pxlcT2 + (pxlcT1=ppxlcSrc[3]) + iRndCtrl) >> 1;
ppxlcDst [3] = (pxlcT1 + (pxlcT2=ppxlcSrc[4]) + iRndCtrl) >> 1;
ppxlcDst [4] = (pxlcT2 + (pxlcT1=ppxlcSrc[5]) + iRndCtrl) >> 1;
ppxlcDst [5] = (pxlcT1 + (pxlcT2=ppxlcSrc[6]) + iRndCtrl) >> 1;
ppxlcDst [6] = (pxlcT2 + (pxlcT1=ppxlcSrc[7]) + iRndCtrl) >> 1;
ppxlcDst [7] = (pxlcT1 + ppxlcSrc[8] + iRndCtrl) >> 1;
ppxlcDst += 8;
ppxlcSrc += 8;
}
ppxlcRef += m_iFrameWidthY;
ppxlcPred += MB_SIZE;
}
}
}
else {
if (!(xRef & 1)) {
Int iRndCtrl = 1 - iRoundingControl;
const PixelC *ppxlcSrc, *ppxlcSrc2;
PixelC *ppxlcDst;
for (iy = 0; iy < iSize; iy++) {
ppxlcDst = ppxlcPred;
ppxlcSrc = ppxlcRef;
ppxlcSrc2 = ppxlcRef + m_iFrameWidthY;
for (ix = 0; ix < iSize; ix+=8) {
ppxlcDst [0] = (ppxlcSrc [0] + ppxlcSrc2 [0] + iRndCtrl) >> 1;
ppxlcDst [1] = (ppxlcSrc [1] + ppxlcSrc2 [1] + iRndCtrl) >> 1;
ppxlcDst [2] = (ppxlcSrc [2] + ppxlcSrc2 [2] + iRndCtrl) >> 1;
ppxlcDst [3] = (ppxlcSrc [3] + ppxlcSrc2 [3] + iRndCtrl) >> 1;
ppxlcDst [4] = (ppxlcSrc [4] + ppxlcSrc2 [4] + iRndCtrl) >> 1;
ppxlcDst [5] = (ppxlcSrc [5] + ppxlcSrc2 [5] + iRndCtrl) >> 1;
ppxlcDst [6] = (ppxlcSrc [6] + ppxlcSrc2 [6] + iRndCtrl) >> 1;
ppxlcDst [7] = (ppxlcSrc [7] + ppxlcSrc2 [7] + iRndCtrl) >> 1;
ppxlcDst += 8;
ppxlcSrc += 8;
ppxlcSrc2 += 8;
}
ppxlcRef += m_iFrameWidthY;
ppxlcPred += MB_SIZE;
}
}
else {
Int iRndCtrl = 2 - iRoundingControl;
PixelC pxlcT1, pxlcT2, pxlcT3, pxlcT4, *ppxlcDst;
const PixelC *ppxlcSrc, *ppxlcSrc2;
for (iy = 0; iy < iSize; iy++) {
ppxlcDst = ppxlcPred;
ppxlcSrc = ppxlcRef;
ppxlcSrc2 = ppxlcRef + m_iFrameWidthY;
for (ix = 0; ix < iSize; ix+=8) {
ppxlcDst [0] = (ppxlcSrc[0] + (pxlcT1=ppxlcSrc[1]) + ppxlcSrc2[0] + (pxlcT3=ppxlcSrc2[1]) + iRndCtrl) >> 2;
ppxlcDst [1] = (pxlcT1 + (pxlcT2=ppxlcSrc[2]) + pxlcT3 + (pxlcT4=ppxlcSrc2[2]) + iRndCtrl) >> 2;
ppxlcDst [2] = (pxlcT2 + (pxlcT1=ppxlcSrc[3]) + pxlcT4 + (pxlcT3=ppxlcSrc2[3]) + iRndCtrl) >> 2;
ppxlcDst [3] = (pxlcT1 + (pxlcT2=ppxlcSrc[4]) + pxlcT3 + (pxlcT4=ppxlcSrc2[4]) + iRndCtrl) >> 2;
ppxlcDst [4] = (pxlcT2 + (pxlcT1=ppxlcSrc[5]) + pxlcT4 + (pxlcT3=ppxlcSrc2[5]) + iRndCtrl) >> 2;
ppxlcDst [5] = (pxlcT1 + (pxlcT2=ppxlcSrc[6]) + pxlcT3 + (pxlcT4=ppxlcSrc2[6]) + iRndCtrl) >> 2;
ppxlcDst [6] = (pxlcT2 + (pxlcT1=ppxlcSrc[7]) + pxlcT4 + (pxlcT3=ppxlcSrc2[7]) + iRndCtrl) >> 2;
ppxlcDst [7] = (pxlcT1 + ppxlcSrc[8] + pxlcT3 + ppxlcSrc2[8] + iRndCtrl) >> 2;
ppxlcDst += 8;
ppxlcSrc += 8;
ppxlcSrc2 += 8;
}
ppxlcRef += m_iFrameWidthY;
ppxlcPred += MB_SIZE;
}
}
}
}
else {
if (!(yRef & 1)) {
if (!(xRef & 1)) { //!bXSubPxl && !bYSubPxl
for (iy = 0; iy < iSize; iy++) {
memcpy (ppxlcPred, ppxlcRef, iSize*sizeof(PixelC));
ppxlcRef += m_iFrameWidthY;
ppxlcPred += MB_SIZE;
}
}
else { //bXSubPxl && !bYSubPxl
for (iy = 0; iy < iSize; iy++){
for (ix = 0; ix < iSize; ix++)
ppxlcPred [ix] = (ppxlcRef [ix] + ppxlcRef [ix + 1] + 1 - iRoundingControl) >> 1;
ppxlcRef += m_iFrameWidthY;
ppxlcPred += MB_SIZE;
}
}
}
else {
const PixelC* ppxlcRefBot;
if (!(xRef & 1)) { //!bXSubPxl&& bYSubPxl
for (iy = 0; iy < iSize; iy++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -