📄 motest.cpp
字号:
/*************************************************************************
This software module was originally developed by
Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation
Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
Bruce Lin (blin@microsoft.com), Microsoft Corporation
(date: March, 1996)
and edited by
Wei Wu (weiwu@stallion.risc.rockwell.com) Rockwell Science Center
and edited by Xuemin Chen (xchen@gi.com) General Instrument Corp.)
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:
motEst.cpp
Abstract:
Motion estimation routines.
Revision History:
Dec 20, 1997: Interlaced tools added by NextLevel Systems
May 9, 1999: tm5 rate control by DemoGraFX, duhoff@mediaone.net
*************************************************************************/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <iostream.h>
#include "typeapi.h"
#include "codehead.h"
#include "global.hpp"
#include "entropy/bitstrm.hpp"
#include "entropy/entropy.hpp"
#include "entropy/huffman.hpp"
#include "mode.hpp"
#include "vopses.hpp"
#include "vopseenc.hpp"
#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
#endif // __MFC_
#define FAVORZERO 129
#define FAVOR_DIRECT 129
#define FAVOR_INTER 512
#define FAVOR_16x16 129
#define FAVOR_FIELD 65 // P-VOP favor field over 8x8 due to fewer MVs
inline Int minimum (Int a, Int b, Int c, Int d)
{
if (a <= b && a <= c && a <= d)
return a;
else if (b <= a && b <= c && b <= d)
return b;
else if (c <= a && c <= b && c <= d)
return c;
else
return d;
}
Void CVideoObjectEncoder::motionEstPVOP ()
{
m_iMAD = 0;
CoordI y = 0;
CMBMode* pmbmd = m_rgmbmd;
CMotionVector* pmv = m_rgmv;
const PixelC* ppxlcOrigY = m_pvopcOrig->pixelsBoundY ();
const PixelC* ppxlcRefY = (m_volmd.bOriginalForME ? m_pvopcRefOrig0 : m_pvopcRefQ0)->pixelsY () + m_iStartInRefToCurrRctY;
Int iMBX, iMBY;
if (m_iMVFileUsage == 1)
readPVOPMVs();
for (iMBY = 0; iMBY < m_iNumMBY; iMBY++, y += MB_SIZE) {
const PixelC* ppxlcOrigMBY = ppxlcOrigY;
const PixelC* ppxlcRefMBY = ppxlcRefY;
CoordI x = 0;
for (iMBX = 0; iMBX < m_iNumMBX; iMBX++, x += MB_SIZE) {
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace (CSite (iMBX, iMBY), "MB_X_Y");
#endif // __TRACE_AND_STATS_
if (m_volmd.volType == ENHN_LAYER && m_vopmd.iRefSelectCode == 3) {
motionEstMB_PVOP (x, y, pmv, pmbmd);
}
else {
copyToCurrBuffY (ppxlcOrigMBY);
pmbmd->m_bFieldDCT=0;
m_iMAD += motionEstMB_PVOP (x, y, pmv, pmbmd, ppxlcRefMBY);
}
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace (CSite (iMBX, iMBY), "MB_X_Y");
m_pbitstrmOut->trace (pmv [0], "MV16");
m_pbitstrmOut->trace (pmv [1], "MV8");
m_pbitstrmOut->trace (pmv [2], "MV8");
m_pbitstrmOut->trace (pmv [3], "MV8");
m_pbitstrmOut->trace (pmv [4], "MV8");
// INTERLACE
if(pmbmd->m_bForwardTop)
m_pbitstrmOut->trace (pmv [6], "MV16x8");
else
m_pbitstrmOut->trace (pmv [5], "MV16x8");
if(pmbmd->m_bForwardBottom)
m_pbitstrmOut->trace (pmv [8], "MV16x8");
else
m_pbitstrmOut->trace (pmv [7], "MV16x8");
// ~INTERLACE
#endif // __TRACE_AND_STATS_
pmbmd++;
pmv += PVOP_MV_PER_REF_PER_MB;
ppxlcOrigMBY += MB_SIZE;
ppxlcRefMBY += MB_SIZE;
}
ppxlcOrigY += m_iFrameWidthYxMBSize;
ppxlcRefY += m_iFrameWidthYxMBSize;
}
if (m_iMVFileUsage == 2)
writePVOPMVs();
}
Void CVideoObjectEncoder::motionEstPVOP_WithShape ()
{
m_iMAD = 0;
CoordI y = m_rctCurrVOPY.top;
CMBMode* pmbmd = m_rgmbmd;
CMotionVector* pmv = m_rgmv;
const PixelC* ppxlcOrigY = m_pvopcOrig->pixelsBoundY ();
const PixelC* ppxlcOrigBY = m_pvopcOrig->pixelsBoundBY ();
const PixelC* ppxlcRefY = (m_volmd.bOriginalForME ? m_pvopcRefOrig0 : m_pvopcRefQ0)->pixelsY () + m_iStartInRefToCurrRctY;
Int iMBX, iMBY;
if (m_iMVFileUsage == 1)
readPVOPMVs();
for (iMBY = 0; iMBY < m_iNumMBY; iMBY++, y += MB_SIZE) {
const PixelC* ppxlcOrigMBY = ppxlcOrigY;
const PixelC* ppxlcOrigMBBY = ppxlcOrigBY;
const PixelC* ppxlcRefMBY = ppxlcRefY;
CoordI x = m_rctCurrVOPY.left;
for (iMBX = 0; iMBX < m_iNumMBX; iMBX++, x += MB_SIZE) {
#ifdef __TRACE_AND_STATS_
if(m_volmd.bShapeOnly==FALSE)
m_pbitstrmOut->trace (CSite (iMBX, iMBY), "MB_X_Y");
#endif // __TRACE_AND_STATS_
copyToCurrBuffWithShapeY (ppxlcOrigMBY, ppxlcOrigMBBY);
decideTransparencyStatus (pmbmd, m_ppxlcCurrMBBY);
if(m_volmd.bShapeOnly==FALSE)
{
if (pmbmd->m_rgTranspStatus [0] == NONE)
{
// new changes X. Chen
pmbmd->m_bFieldDCT=0;
m_iMAD += motionEstMB_PVOP (x, y, pmv, pmbmd, ppxlcRefMBY);
}
else if (pmbmd->m_rgTranspStatus [0] == PARTIAL)
{
// new changes X. Chen
pmbmd->m_bFieldDCT=0;
m_iMAD += motionEstMB_PVOP_WithShape (x, y, pmv, pmbmd, ppxlcRefMBY);
}
#ifdef __TRACE_AND_STATS_
m_pbitstrmOut->trace (CSite (iMBX, iMBY), "MB_X_Y");
m_pbitstrmOut->trace (pmv [0], "MV16");
m_pbitstrmOut->trace (pmv [1], "MV8");
m_pbitstrmOut->trace (pmv [2], "MV8");
m_pbitstrmOut->trace (pmv [3], "MV8");
m_pbitstrmOut->trace (pmv [4], "MV8");
// INTERLACE
// new changes
if(pmbmd->m_bFieldDCT) {
if(pmbmd->m_bForwardTop)
m_pbitstrmOut->trace (pmv [6], "MV16x8");
else
m_pbitstrmOut->trace (pmv [5], "MV16x8");
if(pmbmd->m_bForwardBottom)
m_pbitstrmOut->trace (pmv [8], "MV16x8");
else
m_pbitstrmOut->trace (pmv [7], "MV16x8");
}
// end of new changes
// ~INTERLACE
#endif // __TRACE_AND_STATS_
}
pmbmd++;
pmv += PVOP_MV_PER_REF_PER_MB;
ppxlcOrigMBY += MB_SIZE;
ppxlcOrigMBBY += MB_SIZE;
ppxlcRefMBY += MB_SIZE;
}
ppxlcOrigY += m_iFrameWidthYxMBSize;
ppxlcOrigBY += m_iFrameWidthYxMBSize;
ppxlcRefY += m_iFrameWidthYxMBSize;
}
if (m_iMVFileUsage == 2)
writePVOPMVs();
}
Void CVideoObjectEncoder::motionEstBVOP ()
{
if (m_iMVFileUsage == 1)
readBVOPMVs();
m_iMAD = 0;
CoordI y = 0; // frame-based, always start from 0
CMBMode* pmbmd = m_rgmbmd;
const CMBMode* pmbmdRef = NULL;
const CMotionVector* pmvRef = NULL; //mv in ref frame (for direct mode)
if(m_bCodedFutureRef!=FALSE)
{
pmbmdRef = m_rgmbmdRef;
pmvRef = m_rgmvRef;
}
CMotionVector* pmv = m_rgmv;
CMotionVector* pmvBackward = m_rgmvBackward;
const PixelC* ppxlcOrigY = m_pvopcOrig->pixelsBoundY ();
const PixelC* ppxlcRef0Y = m_pvopcRefQ0->pixelsY () + m_iStartInRefToCurrRctY;
const PixelC* ppxlcRef1Y = m_pvopcRefQ1->pixelsY () + m_iStartInRefToCurrRctY;
Int iMBX, iMBY;
for (iMBY = 0; iMBY < m_iNumMBY; iMBY++, y += MB_SIZE) {
const PixelC* ppxlcOrigMBY = ppxlcOrigY;
const PixelC* ppxlcRef0MBY = ppxlcRef0Y;
const PixelC* ppxlcRef1MBY = ppxlcRef1Y;
CoordI x = 0; // frame-based, always start from 0
for (iMBX = 0; iMBX < m_iNumMBX; iMBX++, x += MB_SIZE) {
pmbmd->m_dctMd = INTER; // B-VOP is always INTER
pmbmd->m_bhas4MVForward = pmbmd->m_bhas4MVBackward = FALSE; //out encoder doesn't support 4 mv in bvop (not even direct mode)
// TPS FIX
if(m_volmd.volType == ENHN_LAYER && (m_vopmd.iRefSelectCode != 3 || m_volmd.iEnhnType == 1)){
pmbmd->m_bColocatedMBSkip= FALSE;
copyToCurrBuffY(ppxlcOrigMBY);
// begin: modified by Sharp(98/3/10)
if ( m_vopmd.iRefSelectCode == 0 )
motionEstMB_BVOP (x, y, pmv, pmvBackward, pmbmd, ppxlcRef0MBY, ppxlcRef1MBY);
else
motionEstMB_BVOP (x, y, pmv, pmvBackward, pmbmd, pmbmdRef, pmvRef, ppxlcRef0MBY, ppxlcRef1MBY, TRUE);
// end: modified by Sharp(98/3/10)
}
else {
pmbmd->m_bColocatedMBSkip = (pmbmdRef==NULL) ? FALSE : pmbmdRef->m_bSkip;
if (pmbmd->m_bColocatedMBSkip) {
pmbmd->m_bSkip = TRUE;
memset (pmv, 0, BVOP_MV_PER_REF_PER_MB * sizeof (CMotionVector));
pmbmd->m_mbType = FORWARD; // can be set to FORWARD mode since the result is the same
}
else {
copyToCurrBuffY (ppxlcOrigMBY);
m_iMAD += m_vopmd.bInterlace ?
motionEstMB_BVOP_Interlaced (x, y, pmv, pmvBackward, pmbmd,
pmbmdRef, pmvRef, ppxlcRef0MBY, ppxlcRef1MBY, pmbmdRef!=NULL) :
motionEstMB_BVOP (x, y, pmv, pmvBackward, pmbmd,
pmbmdRef, pmvRef, ppxlcRef0MBY, ppxlcRef1MBY, pmbmdRef!=NULL);
}
}
pmbmd++;
pmv += BVOP_MV_PER_REF_PER_MB;
pmvBackward += BVOP_MV_PER_REF_PER_MB;
if(m_bCodedFutureRef!=FALSE)
{
pmbmdRef++;
pmvRef += PVOP_MV_PER_REF_PER_MB;
}
ppxlcOrigMBY += MB_SIZE;
ppxlcRef0MBY += MB_SIZE;
ppxlcRef1MBY += MB_SIZE;
}
ppxlcOrigY += m_iFrameWidthYxMBSize;
ppxlcRef0Y += m_iFrameWidthYxMBSize;
ppxlcRef1Y += m_iFrameWidthYxMBSize;
}
if (m_iMVFileUsage == 2)
writeBVOPMVs();
}
Void CVideoObjectEncoder::motionEstBVOP_WithShape ()
{
m_iMAD = 0;
CoordI y = m_rctCurrVOPY.top;
CMBMode* pmbmd = m_rgmbmd;
CMotionVector* pmv = m_rgmv;
CMotionVector* pmvBackward = m_rgmvBackward;
Bool bColocatedMBExist;
const PixelC* ppxlcOrigY = m_pvopcOrig->pixelsBoundY ();
const PixelC* ppxlcOrigBY = m_pvopcOrig->pixelsBoundBY ();
const PixelC* ppxlcRef0Y = m_pvopcRefOrig0->pixelsY () + m_iStartInRefToCurrRctY;
const PixelC* ppxlcRef1Y = m_pvopcRefOrig1->pixelsY () + m_iStartInRefToCurrRctY;
Int iMBX, iMBY;
if (m_iMVFileUsage == 1)
readBVOPMVs();
for (iMBY = 0; iMBY < m_iNumMBY; iMBY++, y += MB_SIZE) {
const PixelC* ppxlcOrigMBY = ppxlcOrigY;
const PixelC* ppxlcOrigMBBY = ppxlcOrigBY;
const PixelC* ppxlcRef0MBY = ppxlcRef0Y;
const PixelC* ppxlcRef1MBY = ppxlcRef1Y;
CoordI x = m_rctCurrVOPY.left;
for (iMBX = 0; iMBX < m_iNumMBX; iMBX++, x += MB_SIZE) {
pmbmd->m_dctMd = INTER; // B-VOP is always INTER
pmbmd->m_bhas4MVForward = pmbmd->m_bhas4MVBackward = FALSE;
copyToCurrBuffWithShapeY (ppxlcOrigMBY, ppxlcOrigMBBY);
decideTransparencyStatus (pmbmd, m_ppxlcCurrMBBY);
if (pmbmd->m_rgTranspStatus [0] != ALL) {
const CMBMode* pmbmdRef;
const CMotionVector* pmvRef;
findColocatedMB (iMBX, iMBY, pmbmdRef, pmvRef);
pmbmd->m_bColocatedMBSkip = (pmbmdRef!=NULL && pmbmdRef->m_bSkip);
// TPS FIX
if(m_volmd.volType == ENHN_LAYER && (m_vopmd.iRefSelectCode != 3 || m_volmd.iEnhnType == 1)) {
pmbmd->m_bColocatedMBSkip= FALSE;
bColocatedMBExist = (pmbmdRef!=NULL);
if (pmbmd->m_rgTranspStatus [0] == NONE) {
m_iMAD += motionEstMB_BVOP (
x, y,
pmv, pmvBackward,
pmbmd,
pmbmdRef, pmvRef,
ppxlcRef0MBY, ppxlcRef1MBY,
bColocatedMBExist
);
}
else if (pmbmd->m_rgTranspStatus [0] == PARTIAL) {
m_iMAD += motionEstMB_BVOP_WithShape (
x, y,
pmv, pmvBackward,
pmbmd,
pmbmdRef, pmvRef,
ppxlcRef0MBY, ppxlcRef1MBY,
bColocatedMBExist
);
}
}
else {
if (pmbmd->m_bColocatedMBSkip) {
pmbmd->m_bSkip = TRUE;
memset (pmv, 0, BVOP_MV_PER_REF_PER_MB * sizeof (CMotionVector));
m_statsMB.nDirectMB++;
pmbmd->m_mbType = FORWARD;
}
else {
bColocatedMBExist = (pmbmdRef!=NULL);
if (pmbmd->m_rgTranspStatus [0] == NONE) {
// new changes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -