www.pudn.com > VC_Standalone.rar > macroblock.cpp


/************************************************************************* 
 AVS1-P2视频解码器源码 
 版权所有:联合信源数字音视频技术(北京)有限公司, (c) 2005-2006  
 
 AVS1-P2 Video Decoder Source Code 
 (c) Copyright, NSCC All Rights Reserved, 2005-2006 
 ************************************************************************* 
 Distributed 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
*************************************************************************/ 
/************************************************************************* 
  文件名称:	macroblock.cpp 
  描    述: 包含三个函数:ParseOnMacroBlock完成宏块码流Parse 
                          McIdctRecOneMarcroBlock完成运动补偿和重构 
                          InitOneMacroBlock完成在求预测mv之前的一些准备工作 
            详细情况见函数具体实现 
*************************************************************************/ 
/************************************************************************* 
  Revision History 
  data          Modification                                    Author 
  2005-2-21      Created                                          jthou 
 *************************************************************************/ 
 
#include "macroblock.h" 
#include "vlc.h" 
#include "global.h" 
#include "pred.h" 
#include "block.h" 
#include "define.h" 
 
/************************************************************************/ 
/* 函数功能:解码过程,从压缩码流中解出宏块信息及亮度色度系数           */ 
/*         - Parse码流                                                  */ 
/*         - VLD                                                        */ 
/*         - 反量化                                                     */ 
/************************************************************************/ 
AVS_HRESULT ParseOneMacroBlock(AVS_BYTE** ppData,  
                               AVS_DWORD dwDataLen,  
                               AVS_DWORD* pdwBitOffset,  
                               STREAMINFO* StrmInfo,  
                               MBINFO* pMbInfo,  
                               AVS_DWORD dwMbIndex,  
                               AVS_INT* pCodCounter,  
                               AVS_SHORT* pLumaResidual,  
                               AVS_SHORT* pChromaResidual) 
{ 
  const AVS_BYTE* pbCurrent = *ppData;  
  AVS_DWORD MbWidth = StrmInfo->SeqInfo.dwMbWidth; 
  AVS_DWORD MbHeight = StrmInfo->SeqInfo.dwHeight; 
  AVS_DWORD PictureType = StrmInfo->ImgInfo.dwImageType;  
  AVS_BOOL  PictureStructure = StrmInfo->ImgInfo.bPictureStructure; 
  AVS_BOOL  SkipModeFlag = StrmInfo->ImgInfo.bSkipModeFlag; 
  AVS_DWORD MbTypeIndex = 0; 
  MBINFO* pCurrMb = &pMbInfo[dwMbIndex]; 
  AVS_INT   mb_type = 0; 
  AVS_INT i; 
  AVS_INT cod_counter = *pCodCounter; 
 
  //应该初始化宏块信息 
  pCurrMb->bHasCbp = FALSE; 
  pCurrMb->dwMbQp = StrmInfo->ImgInfo.dwPictureQp; 
   
 
 
  if(PictureType == I_IMG)   //这部分与标准不符,从参考软件52b中摘出来的 
  { 
    mb_type = 0; 
  } 
  else if(StrmInfo->ImgInfo.bSkipModeFlag) 
  { 
    if(cod_counter == -1) 
    { 
      cod_counter = ue(pbCurrent, pdwBitOffset, dwDataLen); 
    } 
    if(cod_counter == 0) 
    { 
      mb_type = ue(pbCurrent, pdwBitOffset, dwDataLen); 
      if(PictureType == P_IMG) 
        mb_type ++; 
      cod_counter --; 
    } 
    else 
    { 
      cod_counter --; 
      mb_type = 0; 
    } 
  } 
  else 
  { 
    //好像运行不到 
  } 
   
  *pCodCounter = cod_counter; 
 
 
  if(mb_type==0 && PictureType != I_IMG && cod_counter >=0)  //跳过模式 skip mode   
  { 
    if(PictureType == P_IMG)  
      pCurrMb->dwMbType = P_Skip; 
    else 
      pCurrMb->dwMbType = B_Skip; 
    return AVS_NOERROR; 
  } 
  
  if(PictureType == I_IMG) 
  //if(StrmInfo->ImgInfo.dwImageType1 == I_IMG) 
  { 
    if(PictureStructure == 1) 
    { 
      MbTypeIndex = 0; 
      pCurrMb->dwMbType = I_8x8; 
      pCurrMb->dwMvNum = 0; 
    } 
    if(PictureStructure == 0) 
    { 
      MbTypeIndex = 0; 
      pCurrMb->dwMbType = I_8x8; 
      pCurrMb->dwMvNum = 0; 
    } 
  } 
   
  if(PictureType == P_IMG) 
  { 
      MbTypeIndex = mb_type; 
    if(MbTypeIndex >= 5)  //含CBP 
    { 
      pCurrMb->bHasCbp = TRUE; 
      pCurrMb->dwCBPCodeNum = MbTypeIndex - 5; 
      MbTypeIndex = 5; 
    } 
    if(MbTypeIndex == 5) 
      pCurrMb->dwMbType = I_8x8; 
    else  
      pCurrMb->dwMbType = MbTypeIndex + 1; 
  } 
 
  if(PictureType == B_IMG) 
  { 
    if(SkipModeFlag)             
      MbTypeIndex = mb_type + 1; 
    else 
      MbTypeIndex = mb_type; 
 
    if(MbTypeIndex >= 24) 
    { 
      pCurrMb->bHasCbp = TRUE; 
      pCurrMb->dwCBPCodeNum = MbTypeIndex - 24; 
      MbTypeIndex = 24; 
    } 
    if(MbTypeIndex == 24) 
      pCurrMb->dwMbType = I_8x8; 
    else if(MbTypeIndex == 23) //B_8x8 
    { 
      pCurrMb->dwMbType = B_8x8; 
    } 
    else 
      pCurrMb->dwMbType = MbTypeIndex + 6;  
  } 
 
  if(pCurrMb->dwMbType != P_Skip && pCurrMb->dwMbType != B_Skip) 
  { 
    if(pCurrMb->dwMbType == B_8x8) 
    { 
      for(i=0; i<4; i++) 
      { 
        AVS_INT mb_part_type = read_bits(pbCurrent, pdwBitOffset, 2);//u(pbCurrent, pdwBitOffset, dwDataLen, 2); 
        pCurrMb->dwMbPartType[i] = mb_part_type + 30;   
      } 
    } 
 
    if(pCurrMb->dwMbType == I_8x8) 
    { 
      for(i=0; i<4; i++) 
      { 
        pCurrMb->bPredModeFlag[i] = read_bits(pbCurrent, pdwBitOffset, 1);//u(pbCurrent, pdwBitOffset, dwDataLen, 1); 
        if(!pCurrMb->bPredModeFlag[i]) 
          pCurrMb->iIntraLumaPredMode[i] = read_bits(pbCurrent, pdwBitOffset, 2);//u(pbCurrent, pdwBitOffset, dwDataLen, 2); 
        else 
          pCurrMb->iIntraLumaPredMode[i] = -1; 
      } 
      pCurrMb->dwintraChromaPredMode = ue(pbCurrent, pdwBitOffset, dwDataLen); 
       
      if(StrmInfo->SeqInfo.dwChromaFormat == CHROMA422) 
        pCurrMb->dwintraChromaPredMode422 = ue(pbCurrent, pdwBitOffset, dwDataLen); 
    } 
     
    if(pCurrMb->dwMbType == B_8x8) 
    { 
      for(i=0; i<4; i++) 
        pCurrMb->dwMvNum += MvNum[pCurrMb->dwMbPartType[i]]; 
    } 
    else 
      pCurrMb->dwMvNum = MvNum[pCurrMb->dwMbType]; 
 
    AVS_INT mvBwNum = 0; 
    if(pCurrMb->dwMbType == B_8x8) 
    { 
      for(i=0; i<4; i++) 
      { 
        if(pCurrMb->dwMbPartType[i] == SB_Bck_8x8) 
        { 
          mvBwNum ++; 
        } 
      } 
    }   
    AVS_INT mvFwNum = pCurrMb->dwMvNum - mvBwNum; 
    AVS_INT tmpRefIdxFw[4], tmpRefIdxBw[4]; 
 
    AVS_INT x = 0; 
    AVS_INT y = 0; 
     
    if ((!StrmInfo->ImgInfo.bPictureReferenceFlag && PictureType==P_IMG && StrmInfo->ImgInfo.bPictureStructure) ||  
     (!StrmInfo->ImgInfo.bPictureReferenceFlag && !StrmInfo->ImgInfo.bPictureStructure && StrmInfo->ImgInfo.dwImageType1 !=I_IMG))  
    { 
    for(i=0; idwMvNum; i++) 
    { 
      if(pCurrMb->dwMbType == B_8x8) 
      { 
       if(idwMbReferenceIndex[i] = read_bits(pbCurrent, pdwBitOffset, 2); 
        else 
          pCurrMb->dwMbReferenceIndex[i] = read_bits(pbCurrent, pdwBitOffset, 1); 
      } 
    } 
 
    x = 0; 
    y = 0; 
    if(pCurrMb->dwMbType == B_8x8) 
    { 
      for(i=0; i<4; i++) 
      { 
        if(pCurrMb->dwMbPartType[i] == SB_Bck_8x8) 
        { 
          pCurrMb->dwMbReferenceIndex[i] = tmpRefIdxBw[x]; 
          x++; 
        } 
        else if(pCurrMb->dwMbPartType[i] == SB_Direct_8x8) 
        { 
          pCurrMb->dwMbReferenceIndex[i] = 0; 
        } 
        else 
        {  
          pCurrMb->dwMbReferenceIndex[i] = tmpRefIdxFw[y]; 
          y++; 
        } 
      } 
    } 
    } 
     
    AVS_INT tmpmvdFwx[4], tmpmvdFwy[4]; 
    AVS_INT tmpmvdBwx[4], tmpmvdBwy[4]; 
 
    x=y=0; 
 
    for(i=0; idwMvNum; i++) 
    { 
      if(pCurrMb->dwMbType == B_8x8) 
      { 
       if(iiMvDiffX[i] = se(pbCurrent, pdwBitOffset, dwDataLen); 
        pCurrMb->iMvDiffY[i] = se(pbCurrent, pdwBitOffset, dwDataLen);    
      } 
    } 
 
    x = 0; 
    y = 0; 
    if(pCurrMb->dwMbType == B_8x8) 
    { 
      for(i=0; i<4; i++) 
      { 
        if(pCurrMb->dwMbPartType[i] == SB_Bck_8x8) 
        { 
          pCurrMb->iMvDiffX[i] = tmpmvdBwx[x]; 
          pCurrMb->iMvDiffY[i] = tmpmvdBwy[x]; 
          x++; 
        } 
        else if(pCurrMb->dwMbPartType[i] == SB_Direct_8x8) 
        { 
          pCurrMb->iMvDiffX[i] = 0; 
          pCurrMb->iMvDiffY[i] = 0;       
        } 
        else 
        { 
          pCurrMb->iMvDiffX[i] = tmpmvdFwx[y]; 
          pCurrMb->iMvDiffY[i] = tmpmvdFwy[y]; 
          y++; 
        } 
      } 
    } 
 
 
    if(pCurrMb->bHasCbp) 
    { 
        pCurrMb->dwCbp = NCBP[pCurrMb->dwCBPCodeNum][0]; 
    } 
    else 
    { 
        pCurrMb->dwCbp = me(pbCurrent, pdwBitOffset, dwDataLen, pCurrMb->dwMbType); 
    } 
 
    if(StrmInfo->SeqInfo.dwChromaFormat == CHROMA422) 
    { 
      pCurrMb->dwCbp422 = me_chroma422(pbCurrent, pdwBitOffset, dwDataLen, pCurrMb->dwMbType); 
    } 
     
    if((pCurrMb->dwCbp>0 || (pCurrMb->dwCbp422>0 && StrmInfo->SeqInfo.dwChromaFormat == CHROMA422)) &&  
      !StrmInfo->ImgInfo.bFixedPictureQp) //?? 
    { 
      pCurrMb->iMbQpDelta = se(pbCurrent, pdwBitOffset, dwDataLen); 
      pCurrMb->dwMbQp += pCurrMb->iMbQpDelta; //?? 
    } 
 
    for(i=0; i<4; i++) 
    { 
      if (pCurrMb->dwCbp&(1<ImgInfo.bPictureStructure, pLumaResidual+i*64); 
    } 
       
    for(i=0; i<2; i++) 
    { 
      if ((pCurrMb->dwCbp>>4)&(i+1)) 
        ReadChromaCoeff(pbCurrent, dwDataLen, pdwBitOffset, pCurrMb, StrmInfo->ImgInfo.bPictureStructure, pChromaResidual+i*64); 
    } 
     
    if(StrmInfo->SeqInfo.dwChromaFormat == CHROMA422) 
    { 
      for(i=6; i<8; i++) 
      { 
        // ReadChromaCoff422(); 
      } 
    } 
  } 
   
  return AVS_NOERROR; 
} 
 
/************************************************************************/ 
/* 函数功能:运动补偿、反变换、重构                                     */ 
/*         - 运动矢量预测                                               */ 
/*         - 计算预测值                                                 */ 
/*         - 对系数进行反变化得到残差数据                               */ 
/*         - 残差数据和预测数据相加,得到重构图像                       */ 
/************************************************************************/ 
AVS_HRESULT McIdctRecOneMarcroBlock(MBINFO* pMbInfo, 
                                    AVS_DWORD dwMbIndex,  
                                    STREAMINFO* pStrmInfo,  
                                    const VIDEODATA** ppRefFrame,  
                                    VIDEODATA* pCurrFrame, 
                                    AVS_DWORD  dwRefNum, 
                                    AVS_DWORD MbWidth, 
                                    AVS_DWORD MbHeight, 
                                    AVS_DWORD dwCurrDistanceIndex, 
                                    BWREFINFO* pBwRefInfo, 
                                    AVS_SHORT* pLumaResidual, 
                                    AVS_SHORT* pChromaResidual) 
{ 
  AVS_INT block; 
   
  AVS_INT MbX = dwMbIndex%MbWidth; 
  AVS_INT MbY = dwMbIndex/MbWidth; 
  AVS_DWORD imgWidth = pStrmInfo->SeqInfo.dwWidth; 
  AVS_DWORD imgHeight = pStrmInfo->SeqInfo.dwHeight; 
   
  if(dwRefNum == 4) 
    imgHeight >>= 1; 
  AVS_INT uvWidth = imgWidth>>1; 
   
  AVS_DWORD dwImgType = pStrmInfo->ImgInfo.dwImageType; 
 
  AVS_DWORD iImgWidth = imgWidth; 
  AVS_DWORD iUVWidth = uvWidth;  
  AVS_BYTE* pbTopLeftY = pCurrFrame->y; 
  AVS_BYTE* pbTopLeftU = pCurrFrame->u; 
  AVS_BYTE* pbTopLeftV = pCurrFrame->v; 
  AVS_BYTE  Pred[4][8][8]; 
  AVS_BYTE* pPred = &(Pred[0][0][0]); 
  memset(pPred, 0, 4*64*sizeof(AVS_BYTE)); 
   
  AVS_INT i, j; 
 
  dwCurrDistanceIndex = pCurrFrame->dwDistanceIndex; 
   
  InitOneMacroBlock(pMbInfo, dwMbIndex, dwRefNum); 
   
  if(pMbInfo[dwMbIndex].dwMbType == I_8x8)  //帧内预测模式 
  { 
    //亮度预测,变换,重构 
    for(block=0; block<4; block++) 
    {       
      AVS_INT imgX = MbX*16+(block%2)*8; 
      AVS_INT imgY = MbY*16+(block/2)*8; 
      pMbInfo[dwMbIndex].predDir[block] = -1; 
 
      IntraPredLuma(pMbInfo, pbTopLeftY, dwMbIndex, imgWidth, imgHeight, block, pPred+block*64, imgX, imgY); 
      if(pMbInfo[dwMbIndex].dwCbp & (1<ImgInfo.bPictureStructure, pBwRefInfo, pPred); 
 
      for(block=0; block<4; block++) 
      { 
        AVS_INT imgX = MbX*16+(block%2)*8; 
        AVS_INT imgY = MbY*16+(block/2)*8; 
        
        if(pMbInfo[dwMbIndex].dwCbp & (1<