Aprendizaje de la tecnología H.266 / VVC: tecnología Joint Chroma Coding (JCCR)

VVC admite la codificación conjunta del modo de croma residual (JCCR).

El uso (activación) del modo de codificación conjunta de croma se indica mediante el indicador de nivel de TU tu_joint_cbcr_residual_flag , y el modo seleccionado se indica implícitamente mediante los CBF de croma. Si uno o ambos CBF de crominancia de una TU son iguales a 1 (tu_cbf_cb o tu_cbf_cr), hay una bandera tu_joint_cbcr_residual_flag .

En PPS y cabezal de corte, el valor de desplazamiento de crominancia QP en el modo de codificación residual de crominancia conjunta es diferente del valor de desplazamiento de crominancia QP en el modo de codificación residual de crominancia convencional. Estos valores de desplazamiento de crominancia QP se utilizan para derivar el valor de crominancia QP de el bloque codificado utilizando el modo de codificación residual de crominancia conjunta.

El modo JCCR tiene 3 submodos. Cuando el modo de codificación de crominancia conjunta correspondiente (modo 2 en la tabla) se activa en la TU, cuando la TU se cuantifica y decodifica, el desplazamiento de QP de crominancia se agrega a la QP de crominancia derivada de luminancia aplicada (la QP de crominancia derivada de luma aplicada). ). Para otros modos (modo 1 y modo 3 en la tabla), el método de derivación de los QP de crominancia es el mismo que el de los bloques Cb o Cr convencionales.

El proceso de reconstrucción del residuo de crominancia (resCb y resCr) del bloque de transformación de transmisión se muestra en la tabla. Cuando se activa el modo JCCR, se pasa un bloque residual de crominancia conjunta (resJointC [x] [y], y luego considerando información diversa (como tu_cbf_cb tu_cbf_cr, CSign), el bloque residual Cb (resCb) y el bloque de diferencia residual Cr (resCr).

En el lado del codificador, el componente de crominancia conjunta se deriva como sigue. Según el modo (como se muestra en la tabla anterior), el codificador genera resJointC {1,2} de la siguiente manera:

Si mode = 2 (Cb residual simple = C, Cr = CSign * C después de la reconstrucción), entonces de acuerdo con

   -resJointC[ x ][ y ] = ( resCb[ x ][ y ] + CSign * resCr[ x ][ y ] ) / 2.

De lo contrario, si modo = 1 (el residuo único reconstruido Cb = C, Cr = (CSign * C) / 2), entonces de acuerdo con

   -resJointC[ x ][ y ] = ( 4 * resCb[ x ][ y ] + 2 * CSign * resCr[ x ][ y ] ) / 5.

De lo contrario (modo = 3, el único residual reconstruido Cr = C, Cb = (CSign * C) / 2), de acuerdo con

   -resJointC[ x ][ y ] = ( 4 * resCr[ x ][ y ] + 2 * CSign * resCb[ x ][ y ] ) / 5.

 

tu_cbf_cb

tu_cbf_cr

reconstrucción de residuos de Cb y Cr

modo

1

0

resCb [x] [y] = resJointC [x] [y]
resCr [x] [y] = (CSign * resJointC [x] [y]) >> 1

1

1

1

resCb[ x ][ y ] = resJointC[ x ][ y ]
resCr[ x ][ y ] = CSign * resJointC[ x ][ y ]

2

0

1

resCb [x] [y] = (CSign * resJointC [x] [y]) >> 1
resCr [x] [y] = resJointC [x] [y]

3

Los tres modos de codificación de crominancia conjunta anteriores solo son compatibles con el I-chip. En películas P y B, solo se admite el modo 2. Por lo tanto, en las secciones P y B, el elemento de sintaxis tu_joint_cbcr_residual_flag solo existe cuando los cbfs de croma son ambos 1 (es decir, tu_cbf_cb = 1 y tu_cbf_cr = 1).

El modo JCCR se puede combinar con el modo Transform Skip (TS). Para acelerar la velocidad de selección del extremo de codificación, la elección de la transformada JCCR depende de si la codificación independiente de los componentes Cb y Cr selecciona DCT-2 o TS como la mejor transformada, y si hay coeficientes distintos de cero. en la codificación de crominancia independiente. Específicamente dividido en las siguientes dos situaciones:

(1) Cuando los componentes Cb y Cr usan DCT-2 o cuando solo un componente de crominancia (Cb o Cr) tiene un coeficiente distinto de cero y el componente de crominancia selecciona DCT-2, el modo JCCR solo verifica DCT-2. De manera similar, cuando los componentes Cb y Cr usan TS, o cuando solo un componente de croma tiene un coeficiente distinto de cero y el componente selecciona TS, el modo JCCR solo verifica TS.

(2) Cuando las transformaciones selectivas de los componentes Cb y Cr son diferentes, es decir, cuando uno elige DCT-2 y el otro elige TS o viceversa, JCCR prueba tanto DCT-2 como TS. En estos casos, la verificación RD del modo DCT-2 se realiza antes del modo TS, y si los coeficientes de DCT-2 son todos cero, se omite la verificación TS RD.

TrQuant::TrQuant() : m_quant( nullptr )
{
  // allocate temporary buffers

  {
    m_invICT      = m_invICTMem + maxAbsIctMode;
    m_invICT[ 0]  = invTransformCbCr< 0>;
    m_invICT[ 1]  = invTransformCbCr< 1>;
    m_invICT[-1]  = invTransformCbCr<-1>;
    m_invICT[ 2]  = invTransformCbCr< 2>;
    m_invICT[-2]  = invTransformCbCr<-2>;
    m_invICT[ 3]  = invTransformCbCr< 3>;
    m_invICT[-3]  = invTransformCbCr<-3>;
    m_fwdICT      = m_fwdICTMem + maxAbsIctMode;
    m_fwdICT[ 0]  = fwdTransformCbCr< 0>;
    m_fwdICT[ 1]  = fwdTransformCbCr< 1>;
    m_fwdICT[-1]  = fwdTransformCbCr<-1>;
    m_fwdICT[ 2]  = fwdTransformCbCr< 2>;
    m_fwdICT[-2]  = fwdTransformCbCr<-2>;
    m_fwdICT[ 3]  = fwdTransformCbCr< 3>;
    m_fwdICT[-3]  = fwdTransformCbCr<-3>;
  }
}

La función invTransformCbCr es la siguiente, la función es principalmente para obtener el Cr (Cb) residual a través del Cb (Cr) residual

template<int signedMode> void invTransformCbCr( PelBuf &resCb, PelBuf &resCr )
{
  Pel*  cb  = resCb.buf;
  Pel*  cr  = resCr.buf;
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride )
  {
    for( SizeType x = 0; x < resCb.width; x++ )
    {
      if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }
      else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }
      else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }
      else if ( signedMode == -2 )  { cr[x] = (cb[x] == -32768 && sizeof(Pel) == 2) ? 32767 : -cb[x]; }   // non-normative clipping to prevent 16-bit overflow
      else if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }
      else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }
    }
  }
}

La función fwdTransformCbCr es encontrar ResJointC a través de ResCb y ResCr

template<int signedMode> std::pair<int64_t,int64_t> fwdTransformCbCr( const PelBuf &resCb, const PelBuf &resCr, PelBuf& resC1, PelBuf& resC2 )
{
  const Pel*  cb  = resCb.buf;
  const Pel*  cr  = resCr.buf;
  Pel*        c1  = resC1.buf;
  Pel*        c2  = resC2.buf;
  int64_t     d1  = 0;
  int64_t     d2  = 0;
  for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride )
  {
    for( SizeType x = 0; x < resCb.width; x++ )
    {
      int cbx = cb[x], crx = cr[x];
      if      ( signedMode ==  1 )
      {
        c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );
        d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );
      }
      else if ( signedMode == -1 )
      {
        c1[x] = Pel( ( 4*cbx - 2*crx ) / 5 );
        d1   += square( cbx - c1[x] ) + square( crx - (-c1[x]>>1) );
      }
      else if ( signedMode ==  2 )
      {
        c1[x] = Pel( ( cbx + crx ) / 2 );
        d1   += square( cbx - c1[x] ) + square( crx - c1[x] );
      }
      else if ( signedMode == -2 )
      {
        c1[x] = Pel( ( cbx - crx ) / 2 );
        d1   += square( cbx - c1[x] ) + square( crx + c1[x] );
      }
      else if ( signedMode ==  3 )
      {
        c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );
        d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );
      }
      else if ( signedMode == -3 )
      {
        c2[x] = Pel( ( 4*crx - 2*cbx ) / 5 );
        d1   += square( cbx - (-c2[x]>>1) ) + square( crx - c2[x] );
      }
      else
      {
        d1   += square( cbx );
        d2   += square( crx );
      }
    }
  }
  return std::make_pair(d1,d2);
}

 

Supongo que te gusta

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