📄 mvdec.c
字号:
/*************************************************************************This software module was originally developed by Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation (date: July, 1997)and edited by Xuemin Chen (xchen@gi.com), General Instrument Corp.and also edited by Mathias Wien (wien@ient.rwth-aachen.de) RWTH Aachen / Robert BOSCH GmbHand also edited by Fujitsu Laboratories Ltd. (contact: Eishi Morimatsu) Sehoon Son (shson@unitel.co.kr) Samsung AITin 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: mvdec.cAbstract: motion vector decoderRevision History: Dec 20, 1997: Interlaced tools added by General Instrument Corp. Feb.16, 1999: add Quarter Sample Mathias Wien (wien@ient.rwth-aachen.de) Sep.06 1999 : RRV added by Eishi Morimatsu (Fujitsu Laboratories Ltd.) *************************************************************************/#include "typeapi.h"#include "codehead.h"#include "mode.h"#include "global.h"#ifdef UNDER_CE#include "bitstrm.h"#include "huffman.h"#else#include "entropy/bitstrm.h"#include "entropy/huffman.h"#endif#include "vopses.h"#include "vopsedec.h"INLINE Void getDiffMV (CVector *, MVInfo);INLINE Int deScaleMV (Int, Int, Int);INLINE Void fitMvInRange (CVector*, MVInfo);INLINE Void computeDirectForwardMV (CVector, CMotionVector*, CMotionVector*, CMBMode*);INLINE Void decodeMV (CMBMode* pmbmd, CMotionVector* pmv, Bool bLeftBndry, Bool bRightBndry, Bool bTopBndry, Bool bZeroMV, Int iMBX, Int iMBY){#ifdef ENABLE_INTERLACING CVector vctDecode;#endif CVector vctDiff, vctPred; Int iBlk, i; if (pmbmd->m_bSkip || pmbmd->m_dctMd == INTRA || pmbmd->m_dctMd == INTRAQ || bZeroMV) { memset (pmv, 0, PVOP_MV_PER_REF_PER_MB * sizeof (CMotionVector)); return; } if (pmbmd->m_bhas4MVForward) { for (iBlk = Y_BLOCK1; iBlk < U_BLOCK; iBlk++) { if (bLeftBndry || bRightBndry || bTopBndry) if(!main_short_video_header) findMVpredGeneric (&vctPred, pmv, pmbmd, iBlk, iMBX, iMBY); else find8x8MVpredAtBoundary(&vctPred, pmv, bLeftBndry, bRightBndry, bTopBndry, iBlk); else find8x8MVpredInterior (&vctPred, pmv, iBlk); getDiffMV (&vctDiff, g_pVOP->mvInfoForward); ADD_VECT (vctDiff, vctPred); fitMvInRange ((&g_CAddVect), g_pVOP->mvInfoForward); CMOTIONVECTOR_INIT1((&pmv[iBlk]), g_CAddVect); } }#ifdef ENABLE_INTERLACING// INTERLACE else if ((m_vopmd.bInterlace)&&(pmbmd->m_bFieldMV)) { Int iTempX1, iTempY1, iTempX2, iTempY2; find16x16MVpred (&vctPred, pmv, bLeftBndry, bRightBndry, bTopBndry); getDiffMV (&vctDiff, m_vopmd.mvInfoForward); vctDiff.y *= 2; vctPred.y = 2*(vctPred.y / 2); vctDecode = vctDiff + vctPred; //fit in range fitMvInRange ((&vctDecode), m_vopmd.mvInfoForward); CMotionVector* pmv16x8 = pmv +5; if(pmbmd->m_bForwardTop) { pmv16x8++; *pmv16x8 = CMotionVector (vctDecode); //convert to full pel now iTempX1 = pmv16x8->m_vctTrueHalfPel.x; iTempY1 = pmv16x8->m_vctTrueHalfPel.y; pmv16x8++; } else { *pmv16x8 = CMotionVector (vctDecode); //convert to full pel now iTempX1 = pmv16x8->m_vctTrueHalfPel.x; iTempY1 = pmv16x8->m_vctTrueHalfPel.y; pmv16x8++; pmv16x8++; } getDiffMV (&vctDiff, m_vopmd.mvInfoForward); vctDiff.y *= 2; vctPred.y = 2*(vctPred.y / 2); vctDecode = vctDiff + vctPred; //fit in range fitMvInRange ((&vctDecode), m_vopmd.mvInfoForward); if(pmbmd->m_bForwardBottom) { pmv16x8++; *pmv16x8 = CMotionVector (vctDecode); //convert to full pel now iTempX2 = pmv16x8->m_vctTrueHalfPel.x; iTempY2 = pmv16x8->m_vctTrueHalfPel.y; } else { *pmv16x8 = CMotionVector (vctDecode); //convert to full pel now iTempX2 = pmv16x8->m_vctTrueHalfPel.x; iTempY2 = pmv16x8->m_vctTrueHalfPel.y; } Int iTemp; for (UInt i = 1; i < 5; i++) { iTemp = iTempX1 + iTempX2; pmv [i].m_vctTrueHalfPel.x = (iTemp & 3) ? ((iTemp>>1) | 1) : (iTemp>>1); iTemp = iTempY1 + iTempY2; pmv [i].m_vctTrueHalfPel.y = (iTemp & 3) ? ((iTemp>>1) | 1) : (iTemp>>1); pmv [i] = pmv [i].m_vctTrueHalfPel; //convert to full pel now //added mwi pmv[i].computeMV (); } }// ~INTERLACE#endif else // 1 mv { if(!main_short_video_header) findMVpredGeneric (&vctPred, pmv, pmbmd, ALL_Y_BLOCKS, iMBX, iMBY); else find16x16MVpred(&vctPred, pmv, bLeftBndry, bRightBndry, bTopBndry); getDiffMV (&vctDiff, g_pVOP->mvInfoForward); ADD_VECT (vctDiff, vctPred); fitMvInRange ((&g_CAddVect), g_pVOP->mvInfoForward); CMOTIONVECTOR_INIT1(pmv, g_CAddVect); pmv++; for (i = 0; i < 4; i++) { *pmv = *(pmv - 1); pmv++; } }}INLINE Void decodeMVofBVOP (CMotionVector* pmvForward, CMotionVector* pmvBackward, CMBMode* pmbmd, CMotionVector* pmvRef, CMBMode* pmbmdRef){ CVector vctDiff; Int i;#ifdef DUAL_MODE if(pmbmd->m_bSkip == TRUE && m_volmd.volType == ENHN_LAYER && m_vopmd.iRefSelectCode == 0) return;#endif if (pmbmd->m_mbType == FORWARD || pmbmd->m_mbType == INTERPOLATE) { assert (pmbmd->m_bSkip != TRUE); assert (pmbmd->m_bhas4MVForward != TRUE); getDiffMV (&vctDiff, g_pVOP->mvInfoForward);#ifdef ENABLE_INTERLACING // TPS FIX if (pmbmd->m_bFieldMV && m_volmd.volType != ENHN_LAYER) { vctDecode.x = vctDiff.x + m_vctForwardMvPredBVOP[0].x; vctDecode.y = (vctDiff.y + m_vctForwardMvPredBVOP[0].y / 2); fitMvInRange ((&vctDecode), m_vopmd.mvInfoForward); vctDecode.y *= 2; m_vctForwardMvPredBVOP[0] = vctDecode; pmvForward[0] = CMotionVector(vctDecode); pmvForward[1] = pmvForward[0]; pmvForward[2] = pmvForward[0]; getDiffMV(&vctDiff, m_vopmd.mvInfoForward); vctDecode.x = vctDiff.x + m_vctForwardMvPredBVOP[1].x; vctDecode.y = (vctDiff.y + m_vctForwardMvPredBVOP[1].y / 2); fitMvInRange ((&vctDecode), m_vopmd.mvInfoForward); vctDecode.y *= 2; m_vctForwardMvPredBVOP[1] = vctDecode; pmvForward[3] = CMotionVector(vctDecode); pmvForward[4] = pmvForward[3]; } else#endif { ADD_VECT (vctDiff, g_pVO->m_vctForwardMvPredBVOP[0]); fitMvInRange ((&g_CAddVect), g_pVOP->mvInfoForward); g_pVO->m_vctForwardMvPredBVOP[0] = g_CAddVect; g_pVO->m_vctForwardMvPredBVOP[1] = g_CAddVect; CMOTIONVECTOR_INIT1(pmvForward, g_CAddVect); *pmvForward++; for (i = 0; i < 4; i++) { *pmvForward = *(pmvForward - 1); pmvForward++; } } } if (pmbmd->m_mbType == BACKWARD || pmbmd->m_mbType == INTERPOLATE) { assert (pmbmd->m_bSkip != TRUE); assert (pmbmd->m_bhas4MVBackward != TRUE); getDiffMV (&vctDiff, g_pVOP->mvInfoBackward);#ifdef ENABLE_INTERLACING if (pmbmd->m_bFieldMV && m_volmd.volType != ENHN_LAYER) { vctDecode.x = vctDiff.x + m_vctBackwardMvPredBVOP[0].x; vctDecode.y = (vctDiff.y + m_vctBackwardMvPredBVOP[0].y / 2); fitMvInRange ((&vctDecode), m_vopmd.mvInfoBackward); vctDecode.y *= 2; m_vctBackwardMvPredBVOP[0] = vctDecode; CMOTIONVECTOR_INIT1((&pmvBackward[0]), vctDecode); pmvBackward[1] = pmvBackward[0]; pmvBackward[2] = pmvBackward[0]; getDiffMV(&vctDiff, m_vopmd.mvInfoBackward); vctDecode.x = vctDiff.x + m_vctBackwardMvPredBVOP[1].x; vctDecode.y = (vctDiff.y + m_vctBackwardMvPredBVOP[1].y / 2); fitMvInRange ((&vctDecode), m_vopmd.mvInfoBackward); vctDecode.y *= 2; m_vctBackwardMvPredBVOP[1] = vctDecode; CMOTIONVECTOR_INIT1((&pmvBackward[3]), vctDecode); pmvBackward[4] = pmvBackward[3]; } else #endif { ADD_VECT (vctDiff, g_pVO->m_vctBackwardMvPredBVOP[0]); fitMvInRange ((&g_CAddVect), g_pVOP->mvInfoBackward); g_pVO->m_vctBackwardMvPredBVOP[0] = g_CAddVect; g_pVO->m_vctBackwardMvPredBVOP[1] = g_CAddVect; CMOTIONVECTOR_INIT1(pmvBackward, g_CAddVect); *pmvBackward++; for (i = 0; i < 4; i++) { *pmvBackward = *(pmvBackward - 1); pmvBackward++; } } } if (pmbmd->m_mbType == DIRECT) { assert (pmbmd->m_bhas4MVForward != TRUE); #ifdef ENABLE_INTERLACING static MVInfo directInfo = { 32, 1, 1}; if (m_vopmd.bInterlace) { if (!pmbmd->m_bSkip) { if (!m_volmd.bQuarterSample) {// Quarterpel, added by mwi getDiffMV (&pmbmd->m_vctDirectDeltaMV, directInfo); } else { Long lSymbol = decodeSymbol (m_pentrdecMV); pmbmd->m_vctDirectDeltaMV.x = deScaleMV (lSymbol - 32, 0, 1); lSymbol = decodeSymbol (m_pentrdecMV); pmbmd->m_vctDirectDeltaMV.y = deScaleMV (lSymbol - 32, 0, 1); } vctDiff.x = pmbmd->m_vctDirectDeltaMV.x; vctDiff.y = pmbmd->m_vctDirectDeltaMV.y; } else vctDiff.x = vctDiff.y = 0; } else#endif { if (pmbmd->m_bSkip) vctDiff.x = vctDiff.y = 0; else { Long lSymbol = decodeSymbol (m_pentrdecMV); vctDiff.x = deScaleMV (lSymbol - 32, 0, 1); lSymbol = decodeSymbol (m_pentrdecMV); vctDiff.y = deScaleMV (lSymbol - 32, 0, 1); } } computeDirectForwardMV (vctDiff, pmvForward, pmvRef, pmbmdRef); //compute forward mv from diff if(pmbmdRef==NULL) { CMotionVector mvRef; // zero motion vector // transparent reference macroblock if (!g_pVOL->bQuarterSample) // added by mwi pmbmd->m_bhas4MVBackward = pmbmd->m_bhas4MVForward = FALSE; else pmbmd->m_bhas4MVBackward = pmbmd->m_bhas4MVForward = TRUE; backwardMVFromForwardMV (pmvBackward, pmvForward, &mvRef, vctDiff); for (i = 0; i < 4; i++) { pmvForward++; pmvBackward++; backwardMVFromForwardMV(pmvBackward, pmvForward, &mvRef, vctDiff); } } else { pmbmd->m_bhas4MVBackward = pmbmd->m_bhas4MVForward = pmbmdRef->m_bhas4MVForward; //reset 4mv mode// if (pmbmd->m_bhas4MVBackward || pmbmd->m_mbType == DIRECT) { for (i = 0; i < 4; i++) { pmvForward++; pmvBackward++; pmvRef++; backwardMVFromForwardMV (pmvBackward, pmvForward, pmvRef, vctDiff); } }// else// backwardMVFromForwardMV (pmvBackward, pmvForward, pmvRef, vctDiff); } }}INLINE Void computeDirectForwardMV (CVector vctDiff, CMotionVector* pmv, CMotionVector* pmvRef, CMBMode* pmbmdRef){ Int i; if(pmvRef==NULL) { // colocated macroblock is transparent, use zero reference MV CMOTIONVECTOR_INIT1(pmv, vctDiff); *pmv++; for (i = 0; i < 4; i++) { *pmv = *(pmv - 1); pmv++; } } else { Int iPartInterval = g_pVO->m_t - g_pVO->m_tPastRef; Int iFullInterval = g_pVO->m_tFutureRef - g_pVO->m_tPastRef; if (pmbmdRef->m_bhas4MVForward == FALSE) { MUL_VECT (TRUEMVHALFPEL(pmvRef), iPartInterval); if (iFullInterval) { g_CMulVect.x /= iFullInterval; //truncation as per vm g_CMulVect.y /= iFullInterval; //truncation as per vm } ADD_VECT (vctDiff, g_CMulVect); CMOTIONVECTOR_INIT1(pmv, g_CAddVect); *pmv++; for (i = 0; i < 4; i++) { *pmv = *(pmv - 1); pmv++; } } else { for (i = 0; i < 4; i++) { pmv++; pmvRef++; MUL_VECT (TRUEMVHALFPEL(pmvRef), iPartInterval); g_CMulVect.x /= iFullInterval; //truncation as per vm g_CMulVect.y /= iFullInterval; //truncation as per vm ADD_VECT (vctDiff, g_CMulVect); CMOTIONVECTOR_INIT1(pmv, g_CAddVect); } } }}INLINE Void getDiffMV (CVector *vctDiffMV, MVInfo mvinfo) //get half pel{ Int iResidual; Long lSymbol = decodeSymbol (m_pentrdecMV); Int iVLC = lSymbol - 32; if (iVLC != 0) iResidual = getBits (mvinfo.uiFCode - 1); else iResidual = 0; vctDiffMV->x = deScaleMV (iVLC, iResidual, mvinfo.uiScaleFactor); lSymbol = decodeSymbol (m_pentrdecMV); iVLC = lSymbol - 32; if (iVLC != 0) iResidual = getBits (mvinfo.uiFCode - 1); else iResidual = 0; vctDiffMV->y = deScaleMV (iVLC, iResidual, mvinfo.uiScaleFactor);}INLINE Int deScaleMV (Int iVLC, Int iResidual, Int iScaleFactor){ if (iVLC == 0 && iResidual == 0) return 0; else if (iScaleFactor == 1) return (iVLC); else { Int iAbsDiffMVcomponent = abs (iVLC) * iScaleFactor + iResidual - iScaleFactor + 1; //changed a'c to enc return (sign (iVLC) * iAbsDiffMVcomponent); }}INLINE Void fitMvInRange (CVector *vctSrc, MVInfo mvinfo){ Int iMvRange = mvinfo.uiRange; //in half pel unit if (vctSrc->x < -1 * iMvRange) //* 2 to get length of [-range, range] vctSrc->x += 2 * iMvRange; else if (vctSrc->x >= iMvRange) vctSrc->x -= 2 * iMvRange; if (vctSrc->y < -1 * iMvRange) vctSrc->y += 2 * iMvRange; else if (vctSrc->y >= iMvRange) vctSrc->y -= 2 * iMvRange;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -