+static void getmvdregion(block_t* bb, YUV*pic, int posx, int posy, int mvdx, int mvdy, int linex)
+{
+ YUV*p1;
+ YUV*p2;
+ int yy=0,uv=0;
+ int x,y;
+ int yhp = 0, uvhp=0;
+ int uvposx, uvposy;
+ posx = posx*16 + ((mvdx&~1)/2);
+ posy = posy*16 + ((mvdy&~1)/2);
+ p1 = &pic[posy*linex+posx];
+ p2 = &pic[(posy&~1)*linex+(posx&~1)];
+ uvhp = ((mvdx&1)|((mvdx>>1)&1))|((mvdy&2)|((mvdy&1)<<1));
+ yhp = ((mvdy&1)<<1|(mvdx&1));
+
+ /* y */
+ if(yhp==0 || yhp==2) {
+ for(y=0;y<8;y++) {
+ for(x=0;x<8;x++) {
+ bb->y1[yy] = p1[x].y;
+ bb->y2[yy] = p1[x+8].y;
+ bb->y3[yy] = p1[linex*8+x].y;
+ bb->y4[yy] = p1[linex*8+x+8].y;
+ yy++;
+ }
+ p1+=linex;
+
+ if(yhp==2) {
+ yy-=8;
+ for(x=0;x<8;x++) {
+ bb->y1[yy] += p1[x].y; bb->y1[yy] /= 2;
+ bb->y2[yy] += p1[x+8].y; bb->y2[yy] /= 2;
+ bb->y3[yy] += p1[linex*8+x].y; bb->y3[yy] /= 2;
+ bb->y4[yy] += p1[linex*8+x+8].y; bb->y4[yy] /= 2;
+ yy++;
+ }
+ }
+ }
+ } else if(yhp==1 || yhp==3) {
+ for(y=0;y<8;y++) {
+ for(x=0;x<8;x++) {
+ bb->y1[yy] = (p1[x].y + p1[x+1].y);
+ bb->y2[yy] = (p1[x+8].y + p1[x+8+1].y);
+ bb->y3[yy] = (p1[linex*8+x].y + p1[linex*8+x+1].y);
+ bb->y4[yy] = (p1[linex*8+x+8].y + p1[linex*8+x+8+1].y);
+ yy++;
+ }
+ yy-=8;
+ p1+=linex;
+ if(yhp==3) {
+ for(x=0;x<8;x++) {
+ bb->y1[yy] += (p1[x].y + p1[x+1].y); bb->y1[yy]/=4;
+ bb->y2[yy] += (p1[x+8].y + p1[x+8+1].y); bb->y2[yy]/=4;
+ bb->y3[yy] += (p1[linex*8+x].y + p1[linex*8+x+1].y); bb->y3[yy]/=4;
+ bb->y4[yy] += (p1[linex*8+x+8].y + p1[linex*8+x+8+1].y); bb->y4[yy]/=4;
+ yy++;
+ }
+ } else {
+ for(x=0;x<8;x++) {
+ bb->y1[yy]/=2; bb->y2[yy]/=2; bb->y3[yy]/=2; bb->y4[yy]/=2;
+ yy++;
+ }
+ }
+ }
+ }
+
+ /* u,v */
+ if(uvhp==0 || uvhp==2) {
+ for(y=0;y<8;y++) {
+ for(x=0;x<8;x++) {
+ bb->u[uv] = (p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4;
+ bb->v[uv] = (p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4;
+ uv++;
+ }
+ p2+=linex*2;
+ if(uvhp==2) {
+ uv-=8;
+ for(x=0;x<8;x++) {
+ bb->u[uv] += (p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4;
+ bb->v[uv] += (p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4;
+ bb->u[uv] /= 2;
+ bb->v[uv] /= 2;
+ uv++;
+ }
+ }
+ }
+ } else /* uvhp==1 || uvhp==3 */ {
+ for(y=0;y<8;y++) {
+ for(x=0;x<8;x++) {
+ bb->u[uv] = ((p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4+
+ (p2[x*2+2].u + p2[x*2+1+2].u + p2[linex+x*2+2].u + p2[linex+x*2+1+2].u)/4);
+ bb->v[uv] = ((p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4+
+ (p2[x*2+2].v + p2[x*2+1+2].v + p2[linex+x*2+2].v + p2[linex+x*2+1+2].v)/4);
+ uv++;
+ }
+ uv-=8;
+ p2+=linex*2;
+ if(uvhp==3) {
+ for(x=0;x<8;x++) {
+ bb->u[uv] += ((p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4+
+ (p2[x*2+2].u + p2[x*2+1+2].u + p2[linex+x*2+2].u + p2[linex+x*2+1+2].u)/4);
+ bb->v[uv] += ((p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4+
+ (p2[x*2+2].v + p2[x*2+1+2].v + p2[linex+x*2+2].v + p2[linex+x*2+1+2].v)/4);
+ bb->u[uv] /= 4;
+ bb->v[uv] /= 4;
+ uv++;
+ }
+ } else {
+ for(x=0;x<8;x++) {
+ bb->u[uv] /= 2;
+ bb->v[uv] /= 2;
+ uv++;
+ }
+ }
+ }
+ }
+}
+
+static void rgb2yuv(YUV*dest, RGBA*src, int dlinex, int slinex, int width, int height)
+{
+ int x,y;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ int r,g,b;
+ r = src[y*slinex+x].r;
+ g = src[y*slinex+x].g;
+ b = src[y*slinex+x].b;
+ /*dest[y*dlinex+x].y = (r*0.299 + g*0.587 + b*0.114);
+ dest[y*dlinex+x].u = (r*-0.169 + g*-0.332 + b*0.500 + 128.0);
+ dest[y*dlinex+x].v = (r*0.500 + g*-0.419 + b*-0.0813 + 128.0);*/
+
+ //dest[y*dlinex+x].y = 128;//(r*((int)( 0.299*256)) + g*((int)( 0.587*256)) + b*((int)( 0.114 *256)))>>8;
+ dest[y*dlinex+x].y = (r*((int)( 0.299*256)) + g*((int)( 0.587*256)) + b*((int)( 0.114 *256)))>>8;
+ dest[y*dlinex+x].u = (r*((int)(-0.169*256)) + g*((int)(-0.332*256)) + b*((int)( 0.500 *256))+ 128*256)>>8;
+ dest[y*dlinex+x].v = (r*((int)( 0.500*256)) + g*((int)(-0.419*256)) + b*((int)(-0.0813*256))+ 128*256)>>8;
+ }
+ }
+}
+static void copyregion(VIDEOSTREAM*s, YUV*dest, YUV*src, int bx, int by)
+{
+ YUV*p1 = &src[by*s->linex*16+bx*16];
+ YUV*p2 = &dest[by*s->linex*16+bx*16];
+ int y;
+ for(y=0;y<16;y++) {
+ memcpy(p1, p2, 16*sizeof(YUV));
+ p1+=s->linex;p2+=s->linex;
+ }
+}
+
+static void yuv2rgb(RGBA*dest, YUV*src, int linex, int width, int height)
+{
+ int x,y;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ int u,v,yy;
+ u = src[y*linex+x].u;
+ v = src[y*linex+x].v;
+ yy = src[y*linex+x].y;
+ dest[y*linex+x].r = truncate256(yy + ((360*(v-128))>>8));
+ dest[y*linex+x].g = truncate256(yy - ((88*(u-128)+183*(v-128))>>8));
+ dest[y*linex+x].b = truncate256(yy + ((455 * (u-128))>>8));
+ }
+ }
+}
+static void copyblock(VIDEOSTREAM*s, YUV*dest, block_t*b, int bx, int by)
+{
+ YUV*p1 = &dest[(by*16)*s->linex+bx*16];
+ YUV*p2 = &dest[(by*16+8)*s->linex+bx*16];
+ int x,y;
+ for(y=0;y<8;y++) {
+ for(x=0;x<8;x++) {
+ int u,v,yy;
+ p1[x+0].u = b->u[(y/2)*8+(x/2)];
+ p1[x+0].v = b->v[(y/2)*8+(x/2)];
+ p1[x+0].y = b->y1[y*8+x];
+ p1[x+8].u = b->u[(y/2)*8+(x/2)+4];
+ p1[x+8].v = b->v[(y/2)*8+(x/2)+4];
+ p1[x+8].y = b->y2[y*8+x];
+ p2[x+0].u = b->u[(y/2+4)*8+(x/2)];
+ p2[x+0].v = b->v[(y/2+4)*8+(x/2)];
+ p2[x+0].y = b->y3[y*8+x];
+ p2[x+8].u = b->u[(y/2+4)*8+(x/2)+4];
+ p2[x+8].v = b->v[(y/2+4)*8+(x/2)+4];
+ p2[x+8].y = b->y4[y*8+x];
+ }
+ p1+=s->linex;
+ p2+=s->linex;
+ }
+}
+
+static int compareregions(VIDEOSTREAM*s, int bx, int by)
+{
+ int linex = s->width;
+ YUV*p1 = &s->current[by*linex*16+bx*16];
+ YUV*p2 = &s->oldpic[by*linex*16+bx*16];
+ int diff = 0;
+ int x,y;
+ for(y=0;y<16;y++) {
+ for(x=0;x<16;x++) {
+ YUV*m = &p1[x];
+ YUV*n = &p2[x];
+ int y = m->y - n->y;
+ int u = m->u - n->u;
+ int v = m->v - n->v;
+ diff += y*y+(u*u+v*v)/4;
+ }
+ p1+=linex;
+ p2+=linex;
+ }
+ return diff/256;
+}
+
+static inline int valtodc(int val)