[XviD-devel] Rounding
skal
xvid-devel@xvid.org
14 Oct 2002 10:40:46 +0200
On Sun, 2002-10-13 at 23:33, Christoph Lampert wrote:
>
> Hi,
>
>
> I've been looking at rounding of motion vectors half the day. It's done in
> 3 different ways through the code. :( And I don't even think it's right...
>
> I keep reading code like this:
>
> uv_dy = (uv_dy ? SIGN(uv_dy) *
> (roundtab8[ABS(uv_dy) % 8] + (ABS(uv_dy) / 8) * 2) : 0);
>
>
> which is supposed to round from 8th-pel to halfpel. Result is symmetric
> to 0, however, it's not similar to anything I read in the Standard. So
> where is it from?
>
> Also, why the complicated expression using ? and % operator?
>
> My impression is that a simple & and >> should be sufficient
> (if we assume that negative values are shifted in the logical way).
>
> uv_dy = roundtab8[uv_dy & 0x7] + (uv_dy >> 3) * 2;
>
> and similar fof 16th-pel -> halfpel with
>
> uv_dy = roundtab16[uv_dy & 0xF] + (uv_dy >> 4) * 2;
>
> For 16th-Pel this is the same, thought much less complicatedly put.
> FOr 8th-pel there's a difference, and even though it's not large, the
> PSNR gets slightly little higher in average and I believe it's what the
> standard demands.
>
> Or am I wrong here?
>
>
> 8th->half
>
> UV_DY old roundtab8
>
> dy=-15 res=-3 res2=-4
> dy=-14 res=-3 res2=-3
> dy=-13 res=-3 res2=-3
> dy=-12 res=-3 res2=-3
> dy=-11 res=-3 res2=-3
> dy=-10 res=-2 res2=-3
> dy=-9 res=-2 res2=-2
> dy=-8 res=-2 res2=-2
> dy=-7 res=-1 res2=-2
> dy=-6 res=-1 res2=-1
> dy=-5 res=-1 res2=-1
> dy=-4 res=-1 res2=-1
> dy=-3 res=-1 res2=-1
> dy=-2 res= 0 res2=-1
> dy=-1 res= 0 res2= 0
> dy= 0 res= 0 res2= 0
> dy= 1 res= 0 res2= 0
> dy= 2 res= 0 res2= 1
> dy= 3 res= 1 res2= 1
> dy= 4 res= 1 res2= 1
> dy= 5 res= 1 res2= 1
> dy= 6 res= 1 res2= 1
> dy= 7 res= 1 res2= 2
> dy= 8 res= 2 res2= 2
> dy= 9 res= 2 res2= 2
> dy=10 res= 2 res2= 3
> dy=11 res= 3 res2= 3
> dy=12 res= 3 res2= 3
> dy=13 res= 3 res2= 3
> dy=14 res= 3 res2= 3
> dy=15 res= 3 res2= 4
Hi all,
here's the code I've been using for the Round 7-6 -> 7-9
tables during computation of chroma MV:
// Table 7-6 (K=4) (modified)
const int SKL_MB::Rnd_Tab_76[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };
// Table 7-8 (K=2) (modified)
const int SKL_MB::Rnd_Tab_78[ 8] = { 0, 0, 1, 1, 0, 0, 0, 1 };
// Table 7-9 (K=1) (modified)
const int SKL_MB::Rnd_Tab_79[ 4] = { 0, 1, 1, 1 };
typedef SKL_INT16 SKL_MV[2];
#define DIV2RND(x) ( ((x)>>1) | ((x)&1) )
void SKL_MB::Derive_uv_MV_MPEG12(SKL_MV *MV)
{
uv_MV[0] = MV[0][0] >> 1;
uv_MV[1] = MV[0][1] >> 1;
}
void SKL_MB::Derive_uv_MV_From_1MV(int Quarter, SKL_MV *MV)
{
int x = MV[0][0];
int y = MV[0][1];
if (Quarter) { x = DIV2RND(x); y = DIV2RND(y); }
uv_MV[0] = (x>>1) | Rnd_Tab_79[ x & 0x3];
uv_MV[1] = (y>>1) | Rnd_Tab_79[ y & 0x3];
}
void SKL_MB::Derive_uv_MV_From_2MV(int Quarter, SKL_MV *MV)
{
int x = MV[0][0];
int y = MV[0][1];
if (Quarter) { x = DIV2RND(x); y = DIV2RND(y); }
uv_MV[0] = (x>>2) | Rnd_Tab_78[ x & 0x7];
uv_MV[1] = (y>>2) | Rnd_Tab_78[ y & 0x7];
}
void SKL_MB::Derive_uv_MV_From_4MV(int Quarter, SKL_MV *MV)
{
int x = MV[0][0] + MV[1][0] + MV[MV_Stride+0][0] + MV[MV_Stride+1][0];
int y = MV[0][1] + MV[1][1] + MV[MV_Stride+0][1] + MV[MV_Stride+1][1];
if (Quarter) { x = DIV2RND(x); y = DIV2RND(y); }
uv_MV[0] = (x>>3) + Rnd_Tab_76[ x & 0xf ];
uv_MV[1] = (y>>3) + Rnd_Tab_76[ y & 0xf ];
}
#undef DIV2RND
I think it's correct as soon as the '>>' is
really a bitwise shift (signed or unsigned)...
For the half and q-pel truncation, I think using
the shift is the correct way, too
(e.g.:
int Quads = (mv_x&3) | ((mv_y&3)<<2);
mv_x >>= 2;
my_y >>= 2;
for q-pel MV snapping)
bye
Skal