HEVC 亚像素插值offset和shift推导
在调用水平亮度像素插值时,
filter
Int row, col;
Pel c[8];
c[0] = coeff[0];
c[1] = coeff[1];
if ( N >= 4 )
{
c[2] = coeff[2];
c[3] = coeff[3];
}
if ( N >= 6 )
{
c[4] = coeff[4];
c[5] = coeff[5];
}
if ( N == 8 )
{
c[6] = coeff[6];
c[7] = coeff[7];
}
Int cStride = ( isVertical ) ? srcStride : 1;
src -= ( N/2 - 1 ) * cStride;
Int offset;
Pel maxVal;
Int headRoom = std::max
Int shift = IF_FILTER_PREC; // IF_FILTER_PREC=6
assert(shift >= 0);
if ( isLast )
{
shift += (isFirst) ? 0 : headRoom;
offset = 1 << (shift - 1);
offset += (isFirst) ? 0 : IF_INTERNAL_OFFS << IF_FILTER_PREC;
maxVal = (1 << bitDepth) - 1;
}
else
{
shift -= (isFirst) ? headRoom : 0; // shift = 6 – 4 = 2
offset = (isFirst) ? -IF_INTERNAL_OFFS << shift : 0; //offset=-2^15=32768
maxVal = 0;
}
#if VECTOR_CODING__INTERPOLATION_FILTER && (RExt__HIGH_BIT_DEPTH_SUPPORT==0)
if( bitDepth <= 10 )
{
if( N == 8 && !( width & 0x07 ) )
{
Short minVal = 0;
__m128i mmOffset = _mm_set1_epi32( offset );
__m128i mmCoeff[8];
__m128i mmMin = _mm_set1_epi16( minVal );
__m128i mmMax = _mm_set1_epi16( maxVal );
for( Int n = 0 ; n < 8 ; n++ )
mmCoeff[n] = _mm_set1_epi16( c[n] );
for( row = 0 ; row < height ; row++ )
{
for( col = 0 ; col < width ; col += 8 )
{
__m128i mmFiltered = simdInterpolateLuma8( src + col , cStride , mmCoeff , mmOffset , shift );
if( isLast )
{
mmFiltered = simdClip3( mmMin , mmMax , mmFiltered );
}
_mm_storeu_si128( ( __m128i * )( dst + col ) , mmFiltered );
}
src += srcStride;
dst += dstStride;
}
return;
}
}
通过上述观察发现,水平插值后的结果为:
在调用垂直亮度编码时:
filter
Int row, col;
Pel c[8];
c[0] = coeff[0];
c[1] = coeff[1];
if ( N >= 4 )
{
c[2] = coeff[2];
c[3] = coeff[3];
}
if ( N >= 6 )
{
c[4] = coeff[4];
c[5] = coeff[5];
}
if ( N == 8 )
{
c[6] = coeff[6];
c[7] = coeff[7];
}
Int cStride = ( isVertical ) ? srcStride : 1;
src -= ( N/2 - 1 ) * cStride;
Int offset;
Pel maxVal;
Int headRoom = std::max
Int shift = IF_FILTER_PREC;
// with the current settings (IF_INTERNAL_PREC = 14 and IF_FILTER_PREC = 6), though headroom can be
// negative for bit depths greater than 14, shift will remain non-negative for bit depths of 8->20
assert(shift >= 0);
if ( isLast )
{
shift += (isFirst) ? 0 : headRoom; // shift = 6 + 4 = 10
offset = 1 << (shift - 1); // offset = 1 << 9 = 512
offset += (isFirst) ? 0 : IF_INTERNAL_OFFS << IF_FILTER_PREC;
// offset=512+2^(13+6)512=524288 + 512 = 524800
maxVal = (1 << bitDepth) - 1;
}
else
{
shift -= (isFirst) ? headRoom : 0;
offset = (isFirst) ? -IF_INTERNAL_OFFS << shift : 0;
maxVal = 0;
}
#if VECTOR_CODING__INTERPOLATION_FILTER && (RExt__HIGH_BIT_DEPTH_SUPPORT==0)
if( bitDepth <= 10 )
{
if( N == 8 && !( width & 0x07 ) )
{
Short minVal = 0;
__m128i mmOffset = _mm_set1_epi32( offset );
__m128i mmCoeff[8];
__m128i mmMin = _mm_set1_epi16( minVal );
__m128i mmMax = _mm_set1_epi16( maxVal );
for( Int n = 0 ; n < 8 ; n++ )
mmCoeff[n] = _mm_set1_epi16( c[n] );
for( row = 0 ; row < height ; row++ )
{
for( col = 0 ; col < width ; col += 8 )
{
__m128i mmFiltered = simdInterpolateLuma8( src + col , cStride , mmCoeff , mmOffset , shift );
if( isLast )
{
mmFiltered = simdClip3( mmMin , mmMax , mmFiltered );
}
_mm_storeu_si128( ( __m128i * )( dst + col ) , mmFiltered );
}
src += srcStride;
dst += dstStride;
}
return;
}
}
通过观察发现,插值的结果为
推导过程如下