📄 pred.cpp
字号:
/** * Copyright (c) 2006 * OpenAVS Developers. All Rights Reserved. * * Copyright (c) 2005-2006 * NSCC. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *//** * ! \file "pred.c" * \brief Motion vector prediction. */#include "pred.h"#include "define.h"#include "global.h"#include "block.h"static AVS_HRESULT InterPredChromaB8x8( MBINFO* pMbInfo, AVS_INT dwMbIndex, const VIDEODATA ** ppRefFrame, AVS_DWORD dwRefNum, AVS_INT dwMbWidth, AVS_INT dwMbHeight, AVS_INT dwSubMb, AVS_INT dwUV, AVS_BYTE * pPred);AVS_HRESULT IntraPredLuma( MBINFO * pMbInfo, const AVS_BYTE * pbCurrY, AVS_DWORD dwMbIndex, AVS_DWORD dwImgWidth, AVS_DWORD dwImgHeight, AVS_DWORD dwBlockNo, AVS_BYTE* pPred, AVS_DWORD dwImgX, AVS_DWORD dwImgY){ AVS_BOOL LeftBlockAvailable = FALSE; AVS_BOOL UpBlockAvailable = FALSE; AVS_BOOL LeftDownBlockAvailable = FALSE; AVS_BOOL UpRightBlockAvailable = FALSE; AVS_INT intraPredModeA = -1, intraPredModeB = -1; AVS_INT predIntraPredMode = -1; AVS_INT IntraLumaPredMode = -1; AVS_INT mostpredIntraPredMode = -1; AVS_INT BlockX = dwImgX >> 3; AVS_INT BlockY = dwImgY >> 3; AVS_INT dwMb8Width = dwImgWidth>>3; AVS_INT dwMb8Height = dwImgHeight>>3; AVS_DWORD dwMbWidth = dwImgWidth >> 4; dwImgWidth = dwImgWidth; //判断相邻块是否已“可用” if(BlockY > 0) UpBlockAvailable = TRUE; if(BlockY>0 && BlockX<dwMb8Width-1) UpRightBlockAvailable = TRUE; if(BlockX > 0) LeftBlockAvailable = TRUE; if(BlockX>0 && BlockY<dwMb8Height-1 ) LeftDownBlockAvailable = TRUE; if(dwBlockNo == 3) UpRightBlockAvailable = FALSE; if(dwBlockNo != 0) LeftDownBlockAvailable = FALSE; //求预测模式 if(LeftBlockAvailable) { if(dwBlockNo == 0 || dwBlockNo == 2) { if(pMbInfo[dwMbIndex-1].dwMbType == I_8x8) intraPredModeA = pMbInfo[dwMbIndex-1].iIntraLumaPredModeNew[dwBlockNo+1]; else intraPredModeA = 2; } else intraPredModeA = pMbInfo[dwMbIndex].iIntraLumaPredModeNew[dwBlockNo-1]; } if(UpBlockAvailable) { if(dwBlockNo == 0 || dwBlockNo == 1) { if(pMbInfo[dwMbIndex-dwMbWidth].dwMbType == I_8x8) intraPredModeB = pMbInfo[dwMbIndex-dwMbWidth].iIntraLumaPredModeNew[dwBlockNo+2]; else intraPredModeB = 2; } else intraPredModeB = pMbInfo[dwMbIndex].iIntraLumaPredModeNew[dwBlockNo-2]; } if (intraPredModeA == -1 || intraPredModeB == -1) { predIntraPredMode = 2; } else { predIntraPredMode = min(intraPredModeA, intraPredModeB); } if(pMbInfo[dwMbIndex].bPredModeFlag[dwBlockNo]) { IntraLumaPredMode = predIntraPredMode; } else { if(pMbInfo[dwMbIndex].iIntraLumaPredMode[dwBlockNo] < predIntraPredMode) IntraLumaPredMode = pMbInfo[dwMbIndex].iIntraLumaPredMode[dwBlockNo]; else IntraLumaPredMode = pMbInfo[dwMbIndex].iIntraLumaPredMode[dwBlockNo]+1; } pMbInfo[dwMbIndex].iIntraLumaPredModeNew[dwBlockNo] = IntraLumaPredMode; AVS_BYTE c[18], r[18]; AVS_INT i, j; if(LeftBlockAvailable) { for(i=0; i<8; i++) c[i+1] = *(pbCurrY + (dwImgY+i)*dwImgWidth + dwImgX-1); c[0] = c[1]; for(i=0; i<9; i++) { c[i+9] = c[8]; } } if(UpBlockAvailable) { for(i=0; i<8; i++) r[i+1] = *(pbCurrY+(dwImgY-1)*dwImgWidth + dwImgX+i); r[0] = r[1]; for(i=0; i<9; i++) { r[i+9] = r[8]; } } if(LeftDownBlockAvailable) { for(i=0; i<8; i++) c[i+9] = *(pbCurrY+(dwImgY+8+i)*dwImgWidth + dwImgX-1); c[17] = c[16]; } if(UpRightBlockAvailable) { for(i=0; i<8; i++) r[i+9] = *(pbCurrY+(dwImgY-1)*dwImgWidth + dwImgX+8+i); r[17] =r[16]; } if(UpBlockAvailable && LeftBlockAvailable) { r[0] = c[0] = *(pbCurrY+(dwImgY-1)*dwImgWidth + dwImgX-1); } switch(IntraLumaPredMode) { case Intra_8x8_Vertical: for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[i*8+j]=r[j+1]; break; case Intra_8x8_Horizontal: for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[i*8+j]=c[i+1]; break; case Intra_8x8_DC: if(!UpBlockAvailable && !LeftBlockAvailable) { for(i=0;i<8;i++) for(j=0;j<8;j++) pPred[i*8+j] = 128; } else if(UpBlockAvailable && !LeftBlockAvailable) { for(i=0;i<8;i++) for(j=0;j<8;j++) //pPred[j*8+i] = (r[i]+2*r[i+1]+r[i+2]+2)>>2; pPred[i*8+j] = (r[j]+2*r[j+1]+r[j+2]+2)>>2; } else if(!UpBlockAvailable && LeftBlockAvailable) { for(i=0; i<8; i++) for(j=0; j<8; j++) //pPred[j*8+i] = (c[j]+2*c[j+1]+c[j+2]+2)>>2; pPred[i*8+j] = (c[i]+2*c[i+1]+c[i+2]+2)>>2; } else if(UpBlockAvailable && LeftBlockAvailable) { for(i=0; i<8; i++) for(j=0; j<8; j++) //pPred[j*8+i] = (((r[i]+2*r[i+1]+r[i+2]+2)>>2)+((c[j]+2*c[j+1]+c[j+2]+2)>>2))>>1; pPred[i*8+j] = (((r[j]+2*r[j+1]+r[j+2]+2)>>2)+((c[i]+2*c[i+1]+c[i+2]+2)>>2))>>1; } break; case Intra_8x8_Down_Left: for(i=0; i<8; i++) { for(j=0; j<8; j++) //pPred[j*8+i] = (((r[i+j+1]+2*r[i+j+2]+r[i+j+3]+2)>>2)+((c[i+j+1]+2*c[i+j+2]+c[i+j+3]+2)>>2))>>1; pPred[i*8+j] = (((r[i+j+1]+2*r[i+j+2]+r[i+j+3]+2)>>2)+((c[i+j+1]+2*c[i+j+2]+c[i+j+3]+2)>>2))>>1; } break; case Intra_8x8_Down_Right: for(i=0; i<8; i++) { for(j=0; j<8; j++) { if(i==j) pPred[i*8+j] = (c[1]+2*r[0]+r[1]+2)>>2; if(j>i) pPred[i*8+j] = (r[j-i+1]+2*r[j-i]+r[j-i-1]+2)>>2; if(j<i) pPred[i*8+j] = (c[i-j+1]+2*c[i-j]+c[i-j-1]+2)>>2; } } break; default: break; //erro! } return AVS_NOERROR;}AVS_HRESULT IntraPredChroma(MBINFO* pMbInfo, const AVS_BYTE* pbCurrUV, AVS_DWORD dwMbIndex, AVS_DWORD dwMbWidth, AVS_DWORD dwMbHeight, AVS_BYTE* pPred, AVS_DWORD dwUVX, AVS_DWORD dwUVY){ AVS_INT i, j; AVS_BOOL UpBlockAvailable = FALSE; AVS_BOOL LeftBlockAvailable = FALSE; AVS_INT BlockX = dwMbIndex%dwMbWidth; AVS_INT BlockY = dwMbIndex/dwMbWidth; AVS_INT dwUVWidth = dwMbWidth*8; if(BlockX > 0) LeftBlockAvailable = TRUE; if(BlockY > 0) UpBlockAvailable = TRUE; AVS_INT r[10], c[10]; if(LeftBlockAvailable) { for(i=0; i<8; i++) c[i+1] = *(pbCurrUV+(dwUVY+i)*dwUVWidth+dwUVX-1); c[0] = c[1]; c[9] = c[8]; } if(UpBlockAvailable) { for(i=0; i<8; i++) r[i+1] = *(pbCurrUV+(dwUVY-1)*dwUVWidth+dwUVX+i); r[0] = r[1]; r[9] = r[8]; } if(LeftBlockAvailable && UpBlockAvailable) { c[0] = r[0] = *(pbCurrUV+(dwUVY-1)*dwUVWidth+dwUVX-1); } AVS_INT intraChromaPreMode = pMbInfo[dwMbIndex].dwintraChromaPredMode; AVS_INT ih=0, iv=0, ia=0, ib=0, ic=0; switch(intraChromaPreMode) { case Intra_Chroma_DC: if(LeftBlockAvailable && UpBlockAvailable) { for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[j*8+i] = (((r[i]+2*r[i+1]+r[i+2]+2)>>2)+((c[j]+2*c[j+1]+c[j+2]+2)>>2))>>1; } if(!LeftBlockAvailable && UpBlockAvailable) { for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[j*8+i] = (r[i]+2*r[i+1]+r[i+2]+2)>>2; } if(LeftBlockAvailable && !UpBlockAvailable) { for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[j*8+i] = (c[j]+2*c[j+1]+c[j+2]+2)>>2; } if(!LeftBlockAvailable && !UpBlockAvailable) { for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[j*8+i] = 128; } break; case Intra_Chroma_Horizontal: for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[j*8+i] = c[j+1]; break; case Intra_Chroma_Vertical: for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[j*8+i] = r[i+1]; break; case Intra_Chroma_Plane: for(i=0; i<=3; i++) { ih += (i+1)*(r[5+i]-r[3-i]); iv += (i+1)*(c[5+i]-c[3-i]); } ia = (r[8]+c[8])<<4; ib = (17*ih+16)>>5; ic = (17*iv+16)>>5; for(i=0; i<8; i++) for(j=0; j<8; j++) pPred[i*8+j] = Clip((ia+(j-3)*ib+(i-3)*ic+16)>>5); break; default: // error! break; } return AVS_NOERROR;}MOTIONVECTOR ScaleMv(MOTIONVECTOR* pMv, AVS_INT iDistance1, AVS_INT iDistance2){ MOTIONVECTOR mv={0,0}; if(pMv->x != 0) mv.x = sign1(pMv->x)*((abs(pMv->x)*iDistance1*(512/iDistance2)+256) >>9); if(pMv->y != 0) mv.y = sign1(pMv->y)*((abs(pMv->y)*iDistance1*(512/iDistance2)+256) >>9); return mv;}MOTIONVECTOR ScalePredMv(MOTIONVECTOR* pMvA, MOTIONVECTOR* pMvB, MOTIONVECTOR* pMvC, AVS_INT iDistance1, AVS_INT iDistanceA, AVS_INT iDistanceB, AVS_INT iDistanceC){ MOTIONVECTOR MVA, MVB, MVC; MVA = ScaleMv(pMvA, iDistance1, iDistanceA); MVB = ScaleMv(pMvB, iDistance1, iDistanceB); MVC = ScaleMv(pMvC, iDistance1, iDistanceC); AVS_INT VAB = abs(MVA.x - MVB.x) + abs(MVA.y - MVB.y); AVS_INT VBC = abs(MVB.x - MVC.x) + abs(MVB.y - MVC.y); AVS_INT VCA = abs(MVC.x - MVA.x) + abs(MVC.y - MVA.y); AVS_INT FMV = Median(VAB, VBC, VCA); if(FMV == VAB) return MVC; else if(FMV == VBC) return MVA; else return MVB;}static AVS_HRESULT InterPredLuma16x16( MBINFO* pMbInfo, AVS_INT dwMbIndex, const AVS_BYTE* pbRefY, AVS_INT dwMbWidth, AVS_INT dwMbHeight, AVS_INT iBlockDistance, AVS_INT dirBw, AVS_BYTE* pPred){ AVS_BOOL A_BlockAvailable = FALSE; AVS_BOOL B_BlockAvailable = FALSE; AVS_BOOL C_BlockAvailable = FALSE; AVS_BOOL D_BlockAvailable = FALSE; AVS_INT BlockDistanceA=1; AVS_INT BlockDistanceB=1; AVS_INT BlockDistanceC=1; AVS_INT BlockDistanceD=1; AVS_INT RefIdxA = -1; AVS_INT RefIdxB = -1; AVS_INT RefIdxC = -1; AVS_INT RefIdxD = -1; MOTIONVECTOR mvA={0,0}, mvB={0,0}, mvC={0,0}, mvD={0,0}, mvE={0,0}; MOTIONVECTOR MVEPred={0,0}; AVS_INT MbX = dwMbIndex%dwMbWidth; AVS_INT MbY = dwMbIndex/dwMbWidth; if(MbX>0) A_BlockAvailable = TRUE; if(MbY>0) B_BlockAvailable = TRUE; if(MbX>0 && MbY>0) D_BlockAvailable = TRUE; if(MbY>0 && MbX<dwMbWidth-1) C_BlockAvailable = TRUE; if(!A_BlockAvailable || pMbInfo[dwMbIndex-1].dwMbType == I_8x8 || (pMbInfo[dwMbIndex-1].predDir[1] != pMbInfo[dwMbIndex].predDir[0] && pMbInfo[dwMbIndex-1].predDir[1] != PREDDIRSYM)) { mvA.x = mvA.y = 0; BlockDistanceA = 1; RefIdxA = -1; } else { if(!dirBw) { mvA = pMbInfo[dwMbIndex-1].mv[1]; BlockDistanceA = pMbInfo[dwMbIndex-1].iBlockDistance[1]; RefIdxA = pMbInfo[dwMbIndex-1].dwMbReferenceIndex[1]; } else { mvA = pMbInfo[dwMbIndex-1].mvBw[1]; BlockDistanceA = pMbInfo[dwMbIndex-1].iBlockDistanceBw[1]; RefIdxA = pMbInfo[dwMbIndex-1].dwMbReferenceIndexBw[1]; } } if(!B_BlockAvailable || pMbInfo[dwMbIndex-dwMbWidth].dwMbType == I_8x8 || (pMbInfo[dwMbIndex-dwMbWidth].predDir[2] != pMbInfo[dwMbIndex].predDir[0] && pMbInfo[dwMbIndex-dwMbWidth].predDir[2] != PREDDIRSYM)) { mvB.x = mvB.y = 0; BlockDistanceB = 1; RefIdxB = -1; } else { if(!dirBw) { mvB = pMbInfo[dwMbIndex-dwMbWidth].mv[2]; BlockDistanceB = pMbInfo[dwMbIndex-dwMbWidth].iBlockDistance[2]; RefIdxB = pMbInfo[dwMbIndex-dwMbWidth].dwMbReferenceIndex[2]; } else { mvB = pMbInfo[dwMbIndex-dwMbWidth].mvBw[2]; BlockDistanceB = pMbInfo[dwMbIndex-dwMbWidth].iBlockDistanceBw[2]; RefIdxB = pMbInfo[dwMbIndex-dwMbWidth].dwMbReferenceIndexBw[2]; } } if(!D_BlockAvailable || pMbInfo[dwMbIndex-dwMbWidth-1].dwMbType == I_8x8 || (pMbInfo[dwMbIndex-dwMbWidth-1].predDir[3] != pMbInfo[dwMbIndex].predDir[0] && pMbInfo[dwMbIndex-dwMbWidth-1].predDir[3] != PREDDIRSYM)) { mvD.x = mvD.y = 0; BlockDistanceD = 1; RefIdxD = -1; } else { if(!dirBw) { mvD = pMbInfo[dwMbIndex-dwMbWidth-1].mv[3]; BlockDistanceD = pMbInfo[dwMbIndex-dwMbWidth-1].iBlockDistance[3]; RefIdxD = pMbInfo[dwMbIndex-dwMbWidth-1].dwMbReferenceIndex[3]; } else { mvD = pMbInfo[dwMbIndex-dwMbWidth-1].mvBw[3]; BlockDistanceD = pMbInfo[dwMbIndex-dwMbWidth-1].iBlockDistanceBw[3]; RefIdxD = pMbInfo[dwMbIndex-dwMbWidth-1].dwMbReferenceIndexBw[3]; } } if(!C_BlockAvailable) { mvC = mvD;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -