Aprendizaje de código H.266 / VVC: función initIntraMip del código relacionado con la tecnología MIP

La función initIntraMip es principalmente para reducir la resolución de los píxeles de referencia y preparar los datos de entrada para la multiplicación de matrices MIP. La estructura de la función es la siguiente:

MIP se puede dividir en los siguientes tres casos según el tamaño del bloque:

  Tamaño de bloque

Longitud del límite después de reducir la resolución

m_reducedBdrySize

Longitud del límite de salida de la multiplicación de matrices

m_reducedPredSize

mipSizeId = 0 4x4 2 4
mipSizeId = 1 4xN, Nx4, 8x8 4 4
mipSizeId = 2 Bloque de descanso 4 8

La función initIntraMip prepara principalmente los píxeles de referencia del límite y llama a la función prepareInputForPred para preparar los datos de entrada para la predicción MIP.

Nota: Los píxeles de referencia utilizados por MIP son píxeles de referencia sin filtrar.

El código de la función initIntraMip es el siguiente:

void IntraPrediction::initIntraMip( const PredictionUnit &pu, const CompArea &area )
{
  CHECK( area.width > MIP_MAX_WIDTH || area.height > MIP_MAX_HEIGHT, "Error: block size not supported for MIP" );

  // prepare input (boundary) data for prediction
  // 准备输入(边界)数据进行预测
  // MIP使用未滤波的参考像素
  CHECK( m_ipaParam.refFilterFlag, "ERROR: unfiltered refs expected for MIP" );
#if JVET_R0350_MIP_CHROMA_444_SINGLETREE
  Pel       *ptrSrc     = getPredictorPtr(area.compID);//获取参考像素
  const int  srcStride  = m_refBufferStride[area.compID];
  const int  srcHStride = 2;

  m_matrixIntraPred.prepareInputForPred(CPelBuf(ptrSrc, srcStride, srcHStride), area,
                                        pu.cu->slice->getSPS()->getBitDepth(toChannelType(area.compID)), area.compID);
#else
  Pel *ptrSrc = getPredictorPtr( COMPONENT_Y );
  const int srcStride  = m_refBufferStride[COMPONENT_Y];
  const int srcHStride = 2;

  m_matrixIntraPred.prepareInputForPred( CPelBuf( ptrSrc, srcStride, srcHStride ), area, pu.cu->slice->getSPS()->getBitDepth( CHANNEL_TYPE_LUMA ) );
#endif
}

La función prepareInputForPred se divide principalmente en los siguientes cuatro pasos:

  • Paso 1: guarde el tamaño del bloque y calcule los parámetros relacionados con MIP llamando a la función initPredBlockParams
  • Paso 2: Obtenga los datos de entrada (píxeles de referencia en la fila anterior y píxeles de referencia en la columna de la izquierda)
  • Paso 3: Calcule el límite de reducción a través del submuestreo de Haar e impleméntelo a través de la función boundaryDownsampling1D
  • Paso 4: deriva el vector de entrada para la multiplicación de matrices

El código de la función prepareInputForPred es el siguiente

#if JVET_R0350_MIP_CHROMA_444_SINGLETREE
void MatrixIntraPrediction::prepareInputForPred(const CPelBuf &pSrc, const Area &block, const int bitDepth,
                                                const ComponentID compId)
{
  m_component = compId;
#else
void MatrixIntraPrediction::prepareInputForPred(const CPelBuf &pSrc, const Area& block, const int bitDepth)
{
#endif
  // Step 1: Save block size and calculate dependent values
  // Step 1: 保存块大小并计算MIP相关参数
  initPredBlockParams(block);

  // Step 2: Get the input data (left and top reference samples)
  // Step 2: 获取输入数据(左上参考像素)
  // 获取上一行参考像素
  m_refSamplesTop.resize(block.width);
  for (int x = 0; x < block.width; x++)
  {
    m_refSamplesTop[x] = pSrc.at(x + 1, 0);
  }
  // 获取左一列参考像素
  m_refSamplesLeft.resize(block.height);
  for (int y = 0; y < block.height; y++)
  {
    m_refSamplesLeft[y] = pSrc.at(y + 1, 1);
  }

  // Step 3: Compute the reduced boundary via Haar-downsampling (input for the prediction)
  // Step 3: 通过Haar下采样计算缩减边界(预测输入)
  // 下采样后输入向量的尺寸为4或者8
  const int inputSize = 2 * m_reducedBdrySize;
  // 不需要转置时,下采样像素的顺序:先上后左
  m_reducedBoundary          .resize( inputSize );
  // 转置时,下采样像素的顺序:先左后上
  m_reducedBoundaryTransposed.resize( inputSize );

  int* const topReduced = m_reducedBoundary.data();
  boundaryDownsampling1D( topReduced, m_refSamplesTop.data(), block.width, m_reducedBdrySize );

  int* const leftReduced = m_reducedBoundary.data() + m_reducedBdrySize;
  boundaryDownsampling1D( leftReduced, m_refSamplesLeft.data(), block.height, m_reducedBdrySize );

  int* const leftReducedTransposed = m_reducedBoundaryTransposed.data();
  int* const topReducedTransposed  = m_reducedBoundaryTransposed.data() + m_reducedBdrySize;
  for( int x = 0; x < m_reducedBdrySize; x++ )
  {
    topReducedTransposed[x] = topReduced[x];
  }
  for( int y = 0; y < m_reducedBdrySize; y++ )
  {
    leftReducedTransposed[y] = leftReduced[y];
  }

  // Step 4: Rebase the reduced boundary
  // Step 4: 缩小边界
  // 推导矩阵乘法输入向量p,mipSizeId=0/1和mipSizeId=2的推导方法不一样
  m_inputOffset       = m_reducedBoundary[0];
  m_inputOffsetTransp = m_reducedBoundaryTransposed[0];
  const bool hasFirstCol = (m_sizeId < 2);

  m_reducedBoundary          [0] = hasFirstCol ? ((1 << (bitDepth - 1)) - m_inputOffset      ) : 0; // first column of matrix not needed for large blocks
  m_reducedBoundaryTransposed[0] = hasFirstCol ? ((1 << (bitDepth - 1)) - m_inputOffsetTransp) : 0;
  for (int i = 1; i < inputSize; i++)
  {
    m_reducedBoundary          [i] -= m_inputOffset;
    m_reducedBoundaryTransposed[i] -= m_inputOffsetTransp;
  }
}

1. Inicializar los parámetros relacionados con MIP

La función initPredBlockParams se utiliza para inicializar parámetros relacionados con MIP, principalmente para inicializar mipSizeId de acuerdo con el tamaño del bloque actual, y luego para inicializar la longitud del límite después del submuestreo, la longitud del límite de salida de la multiplicación de matrices y el factor de aumento de muestreo de acuerdo con mipSizeId

void MatrixIntraPrediction::initPredBlockParams(const Size& block)
{
  //获得当前块尺寸
  m_blockSize = block;
  // init size index
  // 根据当前块尺寸初始化sizeId
  m_sizeId = getMipSizeId( m_blockSize );
  // init reduced boundary size
  // 初始缩减边界尺寸
  // 对于4x4的块宽度和高度分别缩减为2个像素
  // 对于其余尺寸的块宽度和高度分别缩减为4个像素
  m_reducedBdrySize = (m_sizeId == 0) ? 2 : 4;
  // init reduced prediction size
  // 初始化缩减预测后的尺寸
  // 对于mipSizeId = 0、1的块,MIP预测后输出4x4的块
  // 对于mipSizeId = 2的块,MIP预测后输出8x8的块
  m_reducedPredSize = ( m_sizeId < 2 ) ? 4 : 8;
  // init upsampling factors
  // 初始上采样因子
  m_upsmpFactorHor = m_blockSize.width  / m_reducedPredSize;
  m_upsmpFactorVer = m_blockSize.height / m_reducedPredSize;

  CHECKD( (m_upsmpFactorHor < 1) || ((m_upsmpFactorHor & (m_upsmpFactorHor - 1)) != 0), "Need power of two horizontal upsampling factor." );
  CHECKD( (m_upsmpFactorVer < 1) || ((m_upsmpFactorVer & (m_upsmpFactorVer - 1)) != 0), "Need power of two vertical upsampling factor." );
}

2. Submuestreo

El proceso de muestreo descendente de los píxeles de referencia de límite se implementa mediante la función boundaryDownsampling1D. El proceso de muestreo descendente es en realidad el proceso de promediar los píxeles de referencia de límite. Tomando un bloque de 8x8 como ejemplo, como se muestra en la figura siguiente, hay 8 píxeles de referencia en la fila anterior. Después de promediar dos píxeles de referencia adyacentes, se obtienen 4 píxeles de referencia con muestreo descendente. El proceso de muestreo descendente de los píxeles de referencia en la columna de la izquierda es el mismo.

/*
一维下采样
reducedDst表示下采样后的边界
fullSrc表示下采样前的边界
srcLen表示下采样前的边界长度
dstLen表示下采样后的边界长度
*/
void MatrixIntraPrediction::boundaryDownsampling1D(int* reducedDst, const int* const fullSrc, const SizeType srcLen, const SizeType dstLen)
{
  if (dstLen < srcLen)
  {
    //当下采样后的边界尺寸小于当前块的边界尺寸时,需要进行下采样,下采样操作即相当于求平均操作
    // Create reduced boundary by downsampling 通过下采样创建缩小边界
    const SizeType downsmpFactor = srcLen / dstLen;
    const int log2DownsmpFactor = floorLog2(downsmpFactor);
    const int roundingOffset = (1 << (log2DownsmpFactor - 1));

    SizeType srcIdx = 0;
    for( SizeType dstIdx = 0; dstIdx < dstLen; dstIdx++ )
    {
      int sum = 0;
      for( int k = 0; k < downsmpFactor; k++ )
      {
        sum += fullSrc[srcIdx++];
      }
      reducedDst[dstIdx] = (sum + roundingOffset) >> log2DownsmpFactor;
    }
  }
  else
  {
    // Copy boundary if no downsampling is needed 如果不需要下采样,则复制边界
    for (SizeType i = 0; i < dstLen; ++i)
    {
      reducedDst[i] = fullSrc[i];
    }
  }
}

Una vez finalizado el proceso de muestreo descendente, el píxel de referencia superior y el píxel de referencia izquierdo muestreados se organizan en el vector pTemp de acuerdo con el indicador mipTransposeFlag, la disposición es la siguiente:

  • mipTransposeFlag = 0 时 , pTemp = [redTop, redLeft]
  • mipTransposeFlag = 1 时 , pTemp = [redLeft, redTop]

3. Derivar el vector de entrada para la multiplicación de matrices

El método de derivación del vector de entrada de multiplicación de matrices está relacionado con mipSizeId. El proceso de construcción del vector de entrada p se muestra a continuación, donde inSize = 2 * m_reducedBdrySize

 

Supongo que te gusta

Origin blog.csdn.net/BigDream123/article/details/107018446
Recomendado
Clasificación