transform.cpp

来自「JMVM MPEG MVC/3DAV 测试平台 国际通用标准」· C++ 代码 · 共 1,550 行 · 第 1/3 页

CPP
1,550
字号



Void Transform::xRequantUniform4x4( TCoeff*             piCoeff,
                                    TCoeff*             piCoeffBase,
                                    const QpParameter&  rcQp,
                                    const UChar*        pucScale,
                                    UInt&               ruiAbsSum )
{
  Int normAdjust[] = { 4, 5, 4, 5 };

  ruiAbsSum  = 0;
  for( Int n = 0; n < 16; n++ )
  {
    Int iLevel  = piCoeff[n];
    Int iSign   = iLevel;
    iLevel     -= ( normAdjust[n/4] * normAdjust[n%4] * (Int)piCoeffBase[n] + ( 1 << 5 ) ) >> 6;
    iSign       = iLevel;
    iLevel      = abs( iLevel ) * g_aaiQuantCoef[rcQp.rem()][n];
    
    if( pucScale )
    {
      iLevel    = ( iLevel << 4 ) / pucScale[n];
    }
    iLevel      = ( iLevel + rcQp.add() ) >> rcQp.bits();

    if( 0 != iLevel )
    {
      iSign      >>= 31;
      ruiAbsSum   += iLevel;
      iLevel      ^= iSign;
      iLevel      -= iSign;
      piCoeff [n]  = iLevel;
    }
    else
    {
      piCoeff [n] = 0;
    }
  }
}





Void Transform::xRequantNonUniformChroma( TCoeff*             piCoeff,
                                          TCoeff*             piCoeffBase,
                                          const QpParameter&  rcQp,
                                          const UChar*        pucScale,
                                          UInt&               ruiDcAbs,
                                          UInt&               ruiAcAbs )
{
  Int normAdjust[] = { 4, 5, 4, 5 };

  Int   iLevel    = piCoeff[0];
  UInt  uiSign    = ((UInt)iLevel)>>31;
  iLevel         -= ( (Int)piCoeffBase[0] + 1 ) >> 1;
  uiSign          = ((UInt)iLevel)>>31;
  iLevel          = ( abs( iLevel ) * g_aaiQuantCoef[ rcQp.rem() ][0] );
  if( pucScale )
  {
    iLevel        = ( iLevel << 4 ) / pucScale[0];
  }
  iLevel          = ( iLevel + 2*rcQp.add() ) >> ( rcQp.bits() + 1 );

  ruiDcAbs       += iLevel;
  iLevel          = ( uiSign ? -iLevel : iLevel );
  piCoeff [0]     = iLevel;
  

  UInt uiAcAbs = 0;
  for( int n = 1; n < 16; n++ )
  {
    iLevel      = piCoeff[n];
    Int iSign   = iLevel;
    iLevel     -= ( normAdjust[n/4] * normAdjust[n%4] * (Int)piCoeffBase[n] + ( 1 << 5 ) ) >> 6;
    iSign       = iLevel;
    iLevel      = ( abs( iLevel ) * g_aaiQuantCoef[rcQp.rem()][n] );
    if( pucScale )
    {
      iLevel    = ( iLevel << 4 ) / pucScale[n];
    }
    iLevel      = ( iLevel + rcQp.add() ) >> rcQp.bits();

    if( 0 != iLevel )
    {
      iSign      >>= 31;
      uiAcAbs     += iLevel;
      iLevel      ^= iSign;
      iLevel      -= iSign;
      piCoeff [n]  = iLevel;
    }
    else
    {
      piCoeff [n]  = 0;
    }
  }

  ruiAcAbs += uiAcAbs;
  return;
}



ErrVal Transform::invTransformChromaBlocks( Pel* puc, Int iStride, TCoeff* piCoeff )
{
  xInvTransform4x4Blk( puc,     iStride, piCoeff + 0x00 );
  xInvTransform4x4Blk( puc + 4, iStride, piCoeff + 0x10 );
  puc += iStride << 2;
  xInvTransform4x4Blk( puc,     iStride, piCoeff + 0x20 );
  xInvTransform4x4Blk( puc + 4, iStride, piCoeff + 0x30 );

  return Err::m_nOK;
}






ErrVal Transform::transform4x4Blk( IntYuvMbBuffer* pcOrgData, IntYuvMbBuffer* pcPelData, TCoeff* piCoeff, const UChar* pucScale, UInt& ruiAbsSum )
{
  TCoeff  aiTemp[64];
  XPel*   pOrg    = pcOrgData->getLumBlk();
  XPel*   pRec    = pcPelData->getLumBlk();
  Int     iStride = pcPelData->getLStride();

  xForTransform4x4Blk( pOrg, pRec, iStride, aiTemp );
  xQuantDequantUniform4x4( piCoeff, aiTemp, m_cLumaQp, pucScale, ruiAbsSum );

  ROTRS( 0 == ruiAbsSum, Err::m_nOK );

  xInvTransform4x4Blk( pRec, iStride, aiTemp );

  return Err::m_nOK;
}



ErrVal
Transform::requant4x4Block( IntYuvMbBuffer& rcResData,
                            TCoeff*         piCoeff,
                            TCoeff*         piCoeffBase,
                            const UChar*    pucScale,
                            Bool            bFirstIsDc,
                            UInt&           ruiAbsSum )
{
  Int iDcCoeff = 0;

  //===== trafo =====
  x4x4Trafo( rcResData.getLumBlk (), rcResData.getLStride(), piCoeff );

  // backup the first coefficient
  if (bFirstIsDc)
  {
    iDcCoeff = piCoeff[0];
    piCoeff[0] = 0;
  }

  //===== quantization =====
  xRequantUniform4x4( piCoeff, piCoeffBase, m_cLumaQp, pucScale, ruiAbsSum );

  // restored the first coefficient
  if (bFirstIsDc)
    piCoeff[0] = iDcCoeff;

  return Err::m_nOK;
}


ErrVal
Transform::requantLumaDcCoeffs( TCoeff*         piCoeff,
                                TCoeff*         piCoeffBase,
                                const UChar*    pucScale,
                                UInt&           ruiAbsSum )
{
  // the transform was already performed
  xForTransformLumaDc( piCoeff );

  ruiAbsSum = 0;
  for( UInt n = 0; n < 16; n ++ )
  {
    Int   iLevel = piCoeff[n<<4];
    UInt  uiSign = ((UInt)iLevel)>>31;
    iLevel      -= ( (Int)piCoeffBase[n<<4] + 1 ) >> 1;
    uiSign       = ((UInt)iLevel)>>31;

    iLevel       = abs( iLevel ) * g_aaiQuantCoef[ m_cLumaQp.rem() ][0];
    if( pucScale )
    {
      iLevel     = ( iLevel << 4 ) / pucScale[0];
    }
    iLevel       = ( iLevel + 2 * m_cLumaQp.add() ) >> ( m_cLumaQp.bits() + 1 );
    
    ruiAbsSum    += iLevel;
    iLevel       = ( uiSign ? -iLevel : iLevel );
    piCoeff[n<<4]  = iLevel;
  }

  return Err::m_nOK;
}



ErrVal
Transform::requant8x8Block( IntYuvMbBuffer& rcResData,
                            TCoeff*         piCoeff,
                            TCoeff*         piCoeffBase,
                            const UChar*    pucScale,
                            UInt&           ruiAbsSum )
{
  //===== trafo =====
  x8x8Trafo( rcResData.getLumBlk (), rcResData.getLStride(), piCoeff );

  //===== quantization =====
  xRequantUniform8x8( piCoeff, piCoeffBase, m_cLumaQp, pucScale, ruiAbsSum );

  return Err::m_nOK;
}


ErrVal
Transform::requantChroma( IntYuvMbBuffer& rcResData,
                          TCoeff*         piCoeff,
                          TCoeff*         piCoeffBase,
                          const UChar*    pucScaleU,
                          const UChar*    pucScaleV,
                          UInt&           ruiDcAbs,
                          UInt&           ruiAcAbs )
{
  x4x4Trafo( rcResData.getMbCbAddr(),                                rcResData.getCStride(), piCoeff + 0x00 );
  x4x4Trafo( rcResData.getMbCbAddr() + 4,                            rcResData.getCStride(), piCoeff + 0x10 );
  x4x4Trafo( rcResData.getMbCbAddr() +     4*rcResData.getCStride(), rcResData.getCStride(), piCoeff + 0x20 );
  x4x4Trafo( rcResData.getMbCbAddr() + 4 + 4*rcResData.getCStride(), rcResData.getCStride(), piCoeff + 0x30 );
  x4x4Trafo( rcResData.getMbCrAddr(),                                rcResData.getCStride(), piCoeff + 0x40 );
  x4x4Trafo( rcResData.getMbCrAddr() + 4,                            rcResData.getCStride(), piCoeff + 0x50 );
  x4x4Trafo( rcResData.getMbCrAddr() +     4*rcResData.getCStride(), rcResData.getCStride(), piCoeff + 0x60 );
  x4x4Trafo( rcResData.getMbCrAddr() + 4 + 4*rcResData.getCStride(), rcResData.getCStride(), piCoeff + 0x70 );
  xForTransformChromaDc( piCoeff + 0x00 );
  xForTransformChromaDc( piCoeff + 0x40 );

  xRequantNonUniformChroma( piCoeff+0x00, piCoeffBase+0x00, m_cChromaQp, pucScaleU, ruiDcAbs, ruiAcAbs );
  xRequantNonUniformChroma( piCoeff+0x10, piCoeffBase+0x10, m_cChromaQp, pucScaleU, ruiDcAbs, ruiAcAbs );
  xRequantNonUniformChroma( piCoeff+0x20, piCoeffBase+0x20, m_cChromaQp, pucScaleU, ruiDcAbs, ruiAcAbs );
  xRequantNonUniformChroma( piCoeff+0x30, piCoeffBase+0x30, m_cChromaQp, pucScaleU, ruiDcAbs, ruiAcAbs );

  xRequantNonUniformChroma( piCoeff+0x40, piCoeffBase+0x40, m_cChromaQp, pucScaleV, ruiDcAbs, ruiAcAbs );
  xRequantNonUniformChroma( piCoeff+0x50, piCoeffBase+0x50, m_cChromaQp, pucScaleV, ruiDcAbs, ruiAcAbs );
  xRequantNonUniformChroma( piCoeff+0x60, piCoeffBase+0x60, m_cChromaQp, pucScaleV, ruiDcAbs, ruiAcAbs );
  xRequantNonUniformChroma( piCoeff+0x70, piCoeffBase+0x70, m_cChromaQp, pucScaleV, ruiDcAbs, ruiAcAbs );

  return Err::m_nOK;
}






Void Transform::xForTransform4x4Blk( XPel* pucOrg, XPel* pucRec, Int iStride, TCoeff* piPredCoeff )
{
  Int aai[4][4];
  Int tmp1, tmp2;

  for( Int y = 0; y < 4; y++ )
  {
    Int ai[4];

    ai[0] = pucOrg[0] - pucRec[0];
    ai[1] = pucOrg[1] - pucRec[1];
    ai[2] = pucOrg[2] - pucRec[2];
    ai[3] = pucOrg[3] - pucRec[3];

    tmp1 = ai[0] + ai[3];
    tmp2 = ai[1] + ai[2];

    aai[0][y] = tmp1 + tmp2;
    aai[2][y] = tmp1 - tmp2;

    tmp1 = ai[0] - ai[3];
    tmp2 = ai[1] - ai[2];

    aai[1][y] = tmp1 * 2 + tmp2 ;
    aai[3][y] = tmp1  - tmp2 * 2;
    pucRec += iStride;
    pucOrg += iStride;
  }


  for( Int x = 0; x < 4; x++, piPredCoeff++ )
  {
    tmp1 = aai[x][0] + aai[x][3];
    tmp2 = aai[x][1] + aai[x][2];

    piPredCoeff[0] = tmp1 + tmp2;
    piPredCoeff[8] = tmp1 - tmp2;

    tmp1 = aai[x][0] - aai[x][3];
    tmp2 = aai[x][1] - aai[x][2];

    piPredCoeff[4]  = tmp1 * 2 + tmp2;
    piPredCoeff[12] = tmp1 - tmp2 * 2;
  }
}




Void Transform::xInvTransform4x4Blk( XPel* puc, Int iStride, TCoeff* piCoeff )
{

  Int aai[4][4];
  Int tmp1, tmp2;
  Int x, y;
  Int iStride2=2*iStride;
  Int iStride3=3*iStride;

  for( x = 0; x < 4; x++, piCoeff+=4 )
  {
    tmp1 = piCoeff[0] + piCoeff[2];
    tmp2 = (piCoeff[3]>>1) + piCoeff[1];

    aai[0][x] = tmp1 + tmp2;
	  aai[3][x] = tmp1 - tmp2;

    tmp1 = piCoeff[0] - piCoeff[2];
    tmp2 = (piCoeff[1]>>1) - piCoeff[3];

    aai[1][x] = tmp1 + tmp2;
    aai[2][x] = tmp1 - tmp2;
  }

  for( y = 0; y < 4; y++, puc ++ )
  {
    tmp1 =  aai[y][0] + aai[y][2];
    tmp2 = (aai[y][3]>>1) + aai[y][1];

    puc[0]        = xClip( xRound( tmp1 + tmp2) + puc[0]        );
	  puc[iStride3] = xClip( xRound( tmp1 - tmp2) + puc[iStride3] );

    tmp1 =  aai[y][0] - aai[y][2];
    tmp2 = (aai[y][1]>>1) - aai[y][3];

    puc[iStride]  = xClip( xRound( tmp1 + tmp2) + puc[iStride]  );
	  puc[iStride2] = xClip( xRound( tmp1 - tmp2) + puc[iStride2] );

  }
}





ErrVal Transform::transformMb16x16( IntYuvMbBuffer* pcOrgData, IntYuvMbBuffer* pcPelData, TCoeff* piCoeff, const UChar* pucScale, UInt& ruiDcAbs, UInt& ruiAcAbs )
{
  XPel* pucOrg  = pcOrgData->getMbLumAddr();
  XPel* pucRec  = pcPelData->getMbLumAddr();
  Int   iStride = pcPelData->getLStride();

  TCoeff aiCoeff[256];

  Int x, n;
  Int iOffset = 0;

  for( n = 0; n < 16; n+=4 )
  {
    for( x = 0; x < 4; x++ )
    {
      UInt uiBlk = x+n;
      Int iOffsetBlk = iOffset + (x << 2);
      xForTransform4x4Blk( pucOrg + iOffsetBlk, pucRec + iOffsetBlk, iStride, &aiCoeff[uiBlk<<4] );
    }
    iOffset += iStride << 2;
  }

  xForTransformLumaDc( aiCoeff );

  for( n = 0; n < 16; n ++ )
  {
    xQuantDequantNonUniformLuma( &piCoeff[n<<4], &aiCoeff[n<<4], m_cLumaQp, pucScale, ruiDcAbs, ruiAcAbs );
  }
  
  for( n = 0; n < 16; n ++ )
  {
    aiCoeff[n<<4] = piCoeff[n<<4];
  }

  Int iQpScale = ( g_aaiDequantCoef[m_cLumaQp.rem()][0] << m_cLumaQp.per() );
  if( pucScale )
  {
    iQpScale = ( iQpScale * pucScale[0] ) >> 4;
  }

  invTransformDcCoeff( aiCoeff, iQpScale );

  iOffset = 0;
  for( n = 0; n < 16; n += 4 )
  {
    for( x = 0; x < 4; x++ )
    {
      UInt uiBlk = x+n;
      Int iOffsetBlk = iOffset + (x << 2);
      xInvTransform4x4Blk( pucRec + iOffsetBlk, iStride, &aiCoeff[uiBlk<<4] );
    }
    iOffset += iStride << 2;
  }

  return Err::m_nOK;
}


ErrVal Transform::transformChromaBlocks( XPel* pucOrg, XPel* pucRec, Int iStride, TCoeff* piCoeff, TCoeff* piQuantCoeff, const UChar* pucScale, UInt& ruiDcAbs, UInt& ruiAcAbs )
{
  Int iOffset = 0;

  xForTransform4x4Blk( pucOrg + iOffset, pucRec + iOffset, iStride, piQuantCoeff + 0x00);
  iOffset += 4;
  xForTransform4x4Blk( pucOrg + iOffset, pucRec + iOffset, iStride, piQuantCoeff + 0x10);
  iOffset  = 4*iStride;
  xForTransform4x4Blk( pucOrg + iOffset, pucRec + iOffset, iStride, piQuantCoeff + 0x20);
  iOffset += 4;
  xForTransform4x4Blk( pucOrg + iOffset, pucRec + iOffset, iStride, piQuantCoeff + 0x30);

  xForTransformChromaDc( piQuantCoeff );

  xQuantDequantNonUniformChroma( piCoeff + 0x00, piQuantCoeff + 0x00, m_cChromaQp, pucScale, ruiDcAbs, ruiAcAbs );
  xQuantDequantNonUniformChroma( piCoeff + 0x10, piQuantCoeff + 0x10, m_cChromaQp, pucScale, ruiDcAbs, ruiAcAbs );
  xQuantDequantNonUniformChroma( piCoeff + 0x20, piQuantCoeff + 0x20, m_cChromaQp, pucScale, ruiDcAbs, ruiAcAbs );
  xQuantDequantNonUniformChroma( piCoeff + 0x30, piQuantCoeff + 0x30, m_cChromaQp, pucScale, ruiDcAbs, ruiAcAbs );

  return Err::m_nOK;
}


ErrVal Transform::invTransformChromaBlocks( XPel* puc, Int iStride, TCoeff* piCoeff )
{
  xInvTransform4x4Blk( puc,     iStride, piCoeff + 0x00 );
  xInvTransform4x4Blk( puc + 4, iStride, piCoeff + 0x10 );
  puc += iStride << 2;
  xInvTransform4x4Blk( puc,     iStride, piCoeff + 0x20 );
  xInvTransform4x4Blk( puc + 4, iStride, piCoeff + 0x30 );

  return Err::m_nOK;
}


ErrVal Transform::invTransform4x4Blk( XPel* puc, Int iStride, TCoeff* piCoeff )
{
  xInvTransform4x4Blk( puc, iStride, piCoeff );

  return Err::m_nOK;
}





ErrVal
Transform::transform8x8Blk( IntYuvMbBuffer* pcOrgData,
                            IntYuvMbBuffer* pcPelData,
                            TCoeff*         piCoeff,
                            const UChar*    pucScale,
                            UInt&           ruiAbsSum )
{
  TCoeff  aiTemp[64];
  XPel*   pOrg    = pcOrgData->getLumBlk();
  XPel*   pRec    = pcPelData->getLumBlk();
  Int     iStride = pcPelData->getLStride();

  xForTransform8x8Blk     ( pOrg, pRec, iStride, aiTemp );
  xQuantDequantUniform8x8 ( piCoeff, aiTemp, m_cLumaQp, pucScale, ruiAbsSum );
  invTransform8x8Blk      ( pRec, iStride, aiTemp );

  return Err::m_nOK;
}



ErrVal
Transform::invTransform8x8Blk( XPel*    puc,
                               Int      iStride, 
                               TCoeff*  piCoeff )
{
  Int aai[8][8];
  Int n;

  for( n = 0; n < 8; n++ )
  {
    TCoeff* pi = piCoeff + n*8;
    Int     ai1[8];
    Int     ai2[8];
    
    ai1[0] = pi[0] + pi[4];
    ai1[2] = pi[0] - pi[4];

    ai1[4] = (pi[2]>>1) -  pi[6];
    ai1[6] =  pi[2]     + (pi[6]>>1);

    ai1[1] = pi[5] - pi[3] - pi[7] - (pi[7]>>1);
    ai1[3] = pi[1] + pi[7] - pi[3] - (pi[3]>>1);;
    ai1[5] = pi[7] - pi[1] + pi[5] + (pi[5]>>1);
    ai1[7] = pi[3] + pi[5] + pi[1] + (pi[1]>>1);

    ai2[0] = ai1[0] + ai1[6];
    ai2[6] = ai1[0] - ai1[6];

    ai2[2] = ai1[2] + ai1[4];
    ai2[4] = ai1[2] - ai1[4];

    ai2[1] = ai1[1] + (ai1[7]>>2);
    ai2[7] = ai1[7] - (ai1[1]>>2);

    ai2[3] =  ai1[3]     + (ai1[5]>>2);
    ai2[5] = (ai1[3]>>2) -  ai1[5];

    aai[n][0] = ai2[0] + ai2[7];
    aai[n][1] = ai2[2] + ai2[5];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?