[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