From: kramm <kramm>
Date: Tue, 29 Jul 2003 16:53:09 +0000 (+0000)
Subject: * some refactoring done in block encoding (split into preparation & actual
X-Git-Tag: release-0-5-0~194
X-Git-Url: http://git.asbjorn.it/?a=commitdiff_plain;h=07113b4d6eeaf700f5024a613e90845a7f319de4;p=swftools.git

* some refactoring done in block encoding (split into preparation & actual
  encoding)
* improved COD handling
---

diff --git a/lib/h.263/swfvideo.c b/lib/h.263/swfvideo.c
index 4d5e040..d025b01 100644
--- a/lib/h.263/swfvideo.c
+++ b/lib/h.263/swfvideo.c
@@ -26,6 +26,12 @@
 #include "../rfxswf.h"
 #include "h263tables.c"
 
+/* TODO:
+   - get rid of _vxy, _i endings
+   - use prepare* / write* in encode_blockI
+*/ 
+
+
 #ifdef MAIN
 U16 totalframes = 0;
 #endif
@@ -179,7 +185,7 @@ static double c[8] = {1.0,
 };
 
 static double cc[8];
-int ccquant = -1;
+static int ccquant = -1;
 
 static void preparequant(int quant)
 {
@@ -431,6 +437,7 @@ static void rgb2yuv(YUV*dest, RGBA*src, int dlinex, int slinex, int width, int h
 	}
     }
 }
+
 static void copyregion(VIDEOSTREAM*s, YUV*dest, YUV*src, int bx, int by)
 {
     YUV*p1 = &src[by*s->linex*16+bx*16];
@@ -483,12 +490,12 @@ static void copyblock(VIDEOSTREAM*s, YUV*dest, block_t*b, int bx, int by)
     }
 }
 
-static int compareregions(VIDEOSTREAM*s, int bx, int by)
+static int compare_pic_oldpic(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 diffy=0, diffuv = 0;
     int x,y;
     for(y=0;y<16;y++) {
 	for(x=0;x<16;x++) {
@@ -497,12 +504,48 @@ static int compareregions(VIDEOSTREAM*s, int bx, int by)
 	    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;
+	    diffy += abs(y);
+	    diffuv += abs(u)+abs(v);
 	}
 	p1+=linex;
 	p2+=linex;
     }
-    return diff/256;
+    return diffy + diffuv/4;
+}
+
+static int compare_pic_block(VIDEOSTREAM*s, block_t* b, int bx, int by)
+{
+    int linex = s->width;
+    YUV*y1 = &s->current[(by*2)*linex*8+bx*16];
+    YUV*y2 = &s->current[(by*2)*linex*8+bx*16+8];
+    YUV*y3 = &s->current[(by*2+1)*linex*8+bx*16];
+    YUV*y4 = &s->current[(by*2+1)*linex*8+bx*16+8];
+    YUV*uv = y1;
+    int diffy=0, diffuv = 0;
+    int x,y;
+    for(y=0;y<8;y++) {
+	for(x=0;x<8;x++) {
+	    int yy,u,v;
+	    int y8x = y*8+x;
+	    yy = y1[x].y - b->y1[y8x];
+	    diffy += abs(yy);
+	    yy = y2[x].y - b->y2[y8x];
+	    diffy += abs(yy);
+	    yy = y3[x].y - b->y3[y8x];
+	    diffy += abs(yy);
+	    yy = y4[x].y - b->y4[y8x];
+	    diffy += abs(yy);
+	    u = uv[x*2].u - b->u[y8x];
+	    v = uv[x*2].v - b->v[y8x];
+	    diffuv += (abs(u)+abs(v))*4;
+	}
+	y1+=linex;
+	y2+=linex;
+	y3+=linex;
+	y4+=linex;
+	uv+=linex*2;
+    }
+    return diffy + diffuv/4;
 }
 
 static inline int valtodc(int val)
@@ -660,7 +703,7 @@ static int coefbits8x8(int*bb, int has_dc)
     return bits;
 }
 
-static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
+static int encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
 {
     int t;
     int pos=0;
@@ -668,6 +711,7 @@ static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
 
     if(has_dc) {
 	swf_SetBits(tag, bb[0], 8);
+	bits += 8;
 	pos++;
     }
 
@@ -707,13 +751,14 @@ static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
 		if(rle_params[t].run == run &&
 		   rle_params[t].level == level &&
 		   rle_params[t].last == islast) {
-		    codehuffman(tag, rle, t);
+		    bits += codehuffman(tag, rle, t);
 		    swf_SetBits(tag, sign, 1);
+		    bits += 1;
 		    break;
 		}
 	    }
 	    if(t==RLE_ESCAPE) {
-		codehuffman(tag, rle, RLE_ESCAPE);
+		bits += codehuffman(tag, rle, RLE_ESCAPE);
 		level=bb[pos];
 		/* table 14/h.263 */
 		assert(level);
@@ -723,6 +768,7 @@ static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
 		swf_SetBits(tag, islast, 1);
 		swf_SetBits(tag, run, 6);
 		swf_SetBits(tag, level, 8); //FIXME: fixme??
+		bits += 1 + 6 + 8;
 	    }
 
 	    if(islast)
@@ -730,6 +776,7 @@ static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
 	    pos++;
 	}
     }
+    return bits;
 }
 
 static void quantize(block_t*fb, block_t*b, int has_dc, int quant)
@@ -851,54 +898,6 @@ static void change_quant(int quant, int*dquant)
     *dquant = 0;
 }
 
-static void encode_blockI(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant)
-{
-    block_t fb;
-    block_t b;
-    int dquant=0;
-    int cbpcbits = 0, cbpybits=0;
-
-    getregion(&fb, s->current, bx, by, s->width);
-
-    change_quant(*quant, &dquant);
-    *quant+=dquant;
-
-    dodctandquant(&fb, &b, 1, *quant);
-    //quantize(&fb, &b, 1, *quant);
-
-    //decode_blockI(s, &b, bx, by);
-
-    getblockpatterns(&b, &cbpybits, &cbpcbits, 1);
-
-    if(dquant) {
-	codehuffman(tag, mcbpc_intra, 4+cbpcbits);
-    } else {
-	codehuffman(tag, mcbpc_intra, 0+cbpcbits);
-    }
-
-    codehuffman(tag, cbpy, cbpybits);
-
-    if(dquant) {
-	setQuant(tag, dquant);
-    }
-
-    /* luminance */
-    encode8x8(tag, b.y1, 1, cbpybits&8);
-    encode8x8(tag, b.y2, 1, cbpybits&4);
-    encode8x8(tag, b.y3, 1, cbpybits&2);
-    encode8x8(tag, b.y4, 1, cbpybits&1);
-
-    /* chrominance */
-    encode8x8(tag, b.u, 1, cbpcbits&2);
-    encode8x8(tag, b.v, 1, cbpcbits&1);
-
-    /* reconstruct */
-    dequantize(&b, 1, *quant);
-    doidct(&b);
-    truncateblock(&b);
-    copyblock(s, s->current, &b, bx, by);
-}
-
 static void yuvdiff(block_t*a, block_t*b)
 {
     int t;
@@ -988,237 +987,327 @@ static inline int mvd2index(int px, int py, int x, int y, int xy)
     return x;
 }
 
-static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant)
+typedef struct _iblockdata_t
 {
-    block_t fb;
+    block_t b_i; //transformed quantized coefficients
+    block_t reconstruction;
+    int bits;
+    int bx,by;
+} iblockdata_t;
+
+typedef struct _mvdblockdata_t
+{
+    block_t b_vxy;
+    block_t fbold_vxy;
+    block_t reconstruction;
+    int predictmvdx;
+    int predictmvdy;
+    int x_vxy;
+    int y_vxy;
+    int bits;
+    int bx,by;
+} mvdblockdata_t;
+
+void prepareIBlock(VIDEOSTREAM*s, iblockdata_t*data, int bx, int by, block_t* fb, int*bits)
+{
+    /* consider I-block */
+    block_t fb_i;
     block_t b;
-    int dquant=0;
-    int has_mvd=0;
-    int has_mvd24=0;
+    int y,c;
+    data->bx = bx;
+    data->by = by;
+
+    memcpy(&fb_i, fb, sizeof(block_t));
+    dodctandquant(&fb_i, &data->b_i, 1, s->quant);
+    getblockpatterns(&data->b_i, &y, &c, 1);
+    *bits = 1; //cod
+    *bits += mcbpc_inter[3*4+c].len;
+    *bits += cbpy[y].len;
+    *bits += coefbits8x8(data->b_i.y1, 1);
+    *bits += coefbits8x8(data->b_i.y2, 1);
+    *bits += coefbits8x8(data->b_i.y3, 1);
+    *bits += coefbits8x8(data->b_i.y4, 1);
+    *bits += coefbits8x8(data->b_i.u, 1);
+    *bits += coefbits8x8(data->b_i.v, 1);
+    data->bits = *bits;
+    
+    /* -- reconstruction -- */
+    memcpy(&data->reconstruction,&data->b_i,sizeof(block_t));
+    dequantize(&data->reconstruction, 1, s->quant);
+    doidct(&data->reconstruction);
+    truncateblock(&data->reconstruction);
+}
+
+int writeIBlock(VIDEOSTREAM*s, TAG*tag, iblockdata_t*data)
+{
+    int cbpcbits = 0, cbpybits=0;
+    int mode = 3; /* i block (mode=3) */
     int has_dc=1;
+    int bits = 0;
+    block_t b;
+
+    getblockpatterns(&data->b_i, &cbpybits, &cbpcbits, has_dc);
+    swf_SetBits(tag,0,1); bits += 1; // COD
+    bits += codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
+    bits += codehuffman(tag, cbpy, cbpybits);
+
+    /* luminance */
+    bits += encode8x8(tag, data->b_i.y1, has_dc, cbpybits&8);
+    bits += encode8x8(tag, data->b_i.y2, has_dc, cbpybits&4);
+    bits += encode8x8(tag, data->b_i.y3, has_dc, cbpybits&2);
+    bits += encode8x8(tag, data->b_i.y4, has_dc, cbpybits&1);
+
+    /* chrominance */
+    bits += encode8x8(tag, data->b_i.u, has_dc, cbpcbits&2);
+    bits += encode8x8(tag, data->b_i.v, has_dc, cbpcbits&1);
+
+    copyblock(s, s->current, &data->reconstruction, data->bx, data->by);
+    assert(data->bits == bits);
+    return bits;
+}
+
+void prepareMVDBlock(VIDEOSTREAM*s, mvdblockdata_t*data, int bx, int by, block_t* fb, int*bits)
+{ /* consider mvd(x,y)-block */
+
+    int t;
+    int y,c;
+    block_t fbdiff;
+
+    data->bx = bx;
+    data->by = by;
+    predictmvd(s,bx,by,&data->predictmvdx,&data->predictmvdy);
+
+    data->bits = 65535;
+    data->x_vxy=0;
+    data->y_vxy=0;
+
+
+    if(s->do_motion) {
+	int hx,hy;
+	int bestx=0,besty=0,bestbits=65536;
+	int startx=-32,endx=31;
+	int starty=-32,endy=31;
+
+	if(!bx) startx=0;
+	if(!by) starty=0;
+	if(bx==s->bbx-1) endx=0;
+	if(by==s->bby-1) endy=0;
+
+	for(hx=startx;hx<=endx;hx+=1)
+	for(hy=starty;hy<=endy;hy+=1)
+	{
+	    block_t b;
+	    block_t fbold;
+	    int bits = 0;
+	    memcpy(&fbdiff, fb, sizeof(block_t));
+	    getmvdregion(&fbold, s->oldpic, bx, by, hx, hy, s->linex);
+	    yuvdiff(&fbdiff, &fbold);
+	    dodctandquant(&fbdiff, &b, 0, s->quant);
+	    bits += coefbits8x8(b.y1, 0);
+	    bits += coefbits8x8(b.y2, 0);
+	    bits += coefbits8x8(b.y3, 0);
+	    bits += coefbits8x8(b.y4, 0);
+	    bits += coefbits8x8(b.u, 0);
+	    bits += coefbits8x8(b.v, 0);
+	    if(bits<bestbits) {
+		bestbits = bits;
+		bestx = hx;
+		besty = hy;
+	    }
+	}
+	data->x_vxy = bestx;
+	data->y_vxy = besty;
+    }
+
+    memcpy(&fbdiff, fb, sizeof(block_t));
+    getmvdregion(&data->fbold_vxy, s->oldpic, bx, by, data->x_vxy, data->y_vxy, s->linex);
+    yuvdiff(&fbdiff, &data->fbold_vxy);
+    dodctandquant(&fbdiff, &data->b_vxy, 0, s->quant);
+    getblockpatterns(&data->b_vxy, &y, &c, 0);
+
+    *bits = 1; //cod
+    *bits += mcbpc_inter[0*4+c].len;
+    *bits += cbpy[y^15].len;
+    *bits += mvd[mvd2index(data->predictmvdx, data->predictmvdy, data->x_vxy, data->y_vxy, 0)].len; // (0,0)
+    *bits += mvd[mvd2index(data->predictmvdx, data->predictmvdy, data->x_vxy, data->y_vxy, 1)].len;
+    *bits += coefbits8x8(data->b_vxy.y1, 0);
+    *bits += coefbits8x8(data->b_vxy.y2, 0);
+    *bits += coefbits8x8(data->b_vxy.y3, 0);
+    *bits += coefbits8x8(data->b_vxy.y4, 0);
+    *bits += coefbits8x8(data->b_vxy.u, 0);
+    *bits += coefbits8x8(data->b_vxy.v, 0);
+    data->bits = *bits;
+
+    /* -- reconstruction -- */
+    memcpy(&data->reconstruction, &data->b_vxy, sizeof(block_t));
+    dequantize(&data->reconstruction, 0, s->quant);
+    doidct(&data->reconstruction);
+    for(t=0;t<64;t++) {
+	data->reconstruction.y1[t] = truncate256(data->reconstruction.y1[t] + (int)data->fbold_vxy.y1[t]);
+	data->reconstruction.y2[t] = truncate256(data->reconstruction.y2[t] + (int)data->fbold_vxy.y2[t]);
+	data->reconstruction.y3[t] = truncate256(data->reconstruction.y3[t] + (int)data->fbold_vxy.y3[t]);
+	data->reconstruction.y4[t] = truncate256(data->reconstruction.y4[t] + (int)data->fbold_vxy.y4[t]);
+	data->reconstruction.u[t] = truncate256(data->reconstruction.u[t] + (int)data->fbold_vxy.u[t]);
+	data->reconstruction.v[t] = truncate256(data->reconstruction.v[t] + (int)data->fbold_vxy.v[t]);
+    }
+}
+
+int writeMVDBlock(VIDEOSTREAM*s, TAG*tag, mvdblockdata_t*data)
+{
+    int c = 0, y = 0;
+    /* mvd (0,0) block (mode=0) */
+    int t;
+    int has_dc=0; // mvd w/o mvd24
     int mode = 0;
-    int cbpcbits = 0, cbpybits=0;
-    int diff;
-    int predictmvdx;
-    int predictmvdy;
+    int bx = data->bx;
+    int by = data->by;
+    int bits = 0;
+
+    getblockpatterns(&data->b_vxy, &y, &c, has_dc);
+    swf_SetBits(tag,0,1); bits += 1; // COD
+    bits += codehuffman(tag, mcbpc_inter, mode*4+c);
+    bits += codehuffman(tag, cbpy, y^15);
+
+    /* vector */
+    bits += codehuffman(tag, mvd, mvd2index(data->predictmvdx, data->predictmvdy, data->x_vxy, data->y_vxy, 0));
+    bits += codehuffman(tag, mvd, mvd2index(data->predictmvdx, data->predictmvdy, data->x_vxy, data->y_vxy, 1));
+    s->mvdx[by*s->bbx+bx] = data->x_vxy;
+    s->mvdy[by*s->bbx+bx] = data->y_vxy;
 
-    block_t b_i;
+    /* luminance */
+    bits += encode8x8(tag, data->b_vxy.y1, has_dc, y&8);
+    bits += encode8x8(tag, data->b_vxy.y2, has_dc, y&4);
+    bits += encode8x8(tag, data->b_vxy.y3, has_dc, y&2);
+    bits += encode8x8(tag, data->b_vxy.y4, has_dc, y&1);
+
+    /* chrominance */
+    bits += encode8x8(tag, data->b_vxy.u, has_dc, c&2);
+    bits += encode8x8(tag, data->b_vxy.v, has_dc, c&1);
+
+    copyblock(s, s->current, &data->reconstruction, data->bx, data->by);
+    assert(data->bits == bits);
+    return bits;
+}
+
+
+/* should be called encode_PFrameBlock */
+static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by)
+{
+    block_t fb;
+    int diff1,diff2;
     int bits_i;
+    int bits_vxy;
 
-    block_t fbold_v00;
-    block_t b_v00;
-    int bits_v00 = 65535;
-    int x_v00=0;
-    int y_v00=0;
+    iblockdata_t iblock;
+    mvdblockdata_t mvdblock;
+    
+    getregion(&fb, s->current, bx, by, s->width);
+    prepareIBlock(s, &iblock, bx, by, &fb, &bits_i);
 
-    diff = compareregions(s, bx, by);
+    /* encoded last frame <=> original current block: */
+    diff1 = compare_pic_oldpic(s, bx, by);
+    /* encoded current frame <=> original current block: */
+    diff2 = compare_pic_block(s, &iblock.reconstruction, bx, by);
 
-    if(diff < *quant) {
-	/* TODO: measure the error an I-block encoding would do, and base the decision
-	   on that */
+    if(diff1 <= diff2) {
 	swf_SetBits(tag, 1,1); /* cod=1, block skipped */
 	/* copy the region from the last frame so that we have a complete reconstruction */
 	copyregion(s, s->current, s->oldpic, bx, by);
 	return 1;
     }
+    prepareMVDBlock(s, &mvdblock, bx, by, &fb, &bits_vxy);
 
-    predictmvd(s,bx,by,&predictmvdx,&predictmvdy);
-    getregion(&fb, s->current, bx, by, s->width);
-
-    { /* consider I-block */
-	block_t fb_i;
-	int y,c;
-	memcpy(&fb_i, &fb, sizeof(block_t));
-	dodctandquant(&fb_i, &b_i, 1, *quant);
-	//quantize(&fb_i, &b_i, 1, *quant);
-	getblockpatterns(&b_i, &y, &c, 1);
-	bits_i = 1; //cod
-	bits_i += mcbpc_inter[3*4+c].len;
-	bits_i += cbpy[y].len;
-	bits_i += coefbits8x8(b_i.y1, 1);
-	bits_i += coefbits8x8(b_i.y2, 1);
-	bits_i += coefbits8x8(b_i.y3, 1);
-	bits_i += coefbits8x8(b_i.y4, 1);
-	bits_i += coefbits8x8(b_i.u, 1);
-	bits_i += coefbits8x8(b_i.v, 1);
+    if(bits_i > bits_vxy) {
+	return writeMVDBlock(s, tag, &mvdblock);
+    } else {
+	return writeIBlock(s, tag, &iblock);
     }
+}
 
-    { /* consider mvd(x,y)-block */
-	block_t fbdiff;
-	int y,c;
+/* should be called encode_IFrameBlock */
+static void encode_blockI(TAG*tag, VIDEOSTREAM*s, int bx, int by)
+{
+    block_t fb;
+    block_t b;
+    int dquant=0;
+    int c = 0, y=0;
 
-	x_v00=0;
-	y_v00=0;
+    getregion(&fb, s->current, bx, by, s->width);
 
-	if(s->do_motion) {
-	    int hx,hy;
-	    int bestx=0,besty=0,bestbits=65536;
-	    int startx=-32,endx=31;
-	    int starty=-32,endy=31;
+    change_quant(s->quant, &dquant);
+    s->quant+=dquant;
 
-	    if(!bx) startx=0;
-	    if(!by) starty=0;
-	    if(bx==s->bbx-1) endx=0;
-	    if(by==s->bby-1) endy=0;
+    dodctandquant(&fb, &b, 1, s->quant);
 
-	    for(hx=startx;hx<=endx;hx+=1)
-	    for(hy=starty;hy<=endy;hy+=1)
-	    {
-		block_t b;
-		block_t fbold;
-		int bits = 0;
-		memcpy(&fbdiff, &fb, sizeof(block_t));
-		getmvdregion(&fbold, s->oldpic, bx, by, hx, hy, s->linex);
-		yuvdiff(&fbdiff, &fbold);
-		dodctandquant(&fbdiff, &b, 0, *quant);
-		//quantize(&fbdiff, &b, 0, *quant);
-		bits += coefbits8x8(b.y1, 0);
-		bits += coefbits8x8(b.y2, 0);
-		bits += coefbits8x8(b.y3, 0);
-		bits += coefbits8x8(b.y4, 0);
-		bits += coefbits8x8(b.u, 0);
-		bits += coefbits8x8(b.v, 0);
-		if(bits<bestbits) {
-		    bestbits = bits;
-		    bestx = hx;
-		    besty = hy;
-		}
-	    }
-	    x_v00 = bestx;
-	    y_v00 = besty;
-	}
+    getblockpatterns(&b, &y, &c, 1);
 
-	memcpy(&fbdiff, &fb, sizeof(block_t));
-	getmvdregion(&fbold_v00, s->oldpic, bx, by, x_v00, y_v00, s->linex);
-	yuvdiff(&fbdiff, &fbold_v00);
-	dodctandquant(&fbdiff, &b_v00, 0, *quant);
-	//quantize(&fbdiff, &b_v00, 0, *quant);
-	getblockpatterns(&b_v00, &y, &c, 0);
-
-	bits_v00 = 1; //cod
-	bits_v00 += mcbpc_inter[0*4+c].len;
-	bits_v00 += cbpy[y^15].len;
-	bits_v00 += mvd[mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 0)].len; // (0,0)
-	bits_v00 += mvd[mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 1)].len;
-	bits_v00 += coefbits8x8(b_v00.y1, 0);
-	bits_v00 += coefbits8x8(b_v00.y2, 0);
-	bits_v00 += coefbits8x8(b_v00.y3, 0);
-	bits_v00 += coefbits8x8(b_v00.y4, 0);
-	bits_v00 += coefbits8x8(b_v00.u, 0);
-	bits_v00 += coefbits8x8(b_v00.v, 0);
+    if(dquant) {
+	codehuffman(tag, mcbpc_intra, 4+c);
+    } else {
+	codehuffman(tag, mcbpc_intra, 0+c);
     }
 
-    if(bits_i > bits_v00)
-    {
-	/* mvd (0,0) block (mode=0) */
-	int t;
-	mode = 0; // mvd w/o mvd24
-	has_dc = 0;
-	memcpy(&b, &b_v00, sizeof(block_t));
-
-	getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
-	swf_SetBits(tag,0,1); // COD
-	codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
-	codehuffman(tag, cbpy, cbpybits^15);
-
-	/* vector */
-	codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 0));
-	codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 1));
-	s->mvdx[by*s->bbx+bx] = x_v00;
-	s->mvdy[by*s->bbx+bx] = y_v00;
-
-	/* luminance */
-	encode8x8(tag, b.y1, has_dc, cbpybits&8);
-	encode8x8(tag, b.y2, has_dc, cbpybits&4);
-	encode8x8(tag, b.y3, has_dc, cbpybits&2);
-	encode8x8(tag, b.y4, has_dc, cbpybits&1);
-
-	/* chrominance */
-	encode8x8(tag, b.u, has_dc, cbpcbits&2);
-	encode8x8(tag, b.v, has_dc, cbpcbits&1);
-
-	/* -- reconstruction -- */
-	dequantize(&b, 0, *quant);
-	doidct(&b);
-	for(t=0;t<64;t++) {
-	    b.y1[t] = truncate256(b.y1[t] + (int)fbold_v00.y1[t]);
-	    b.y2[t] = truncate256(b.y2[t] + (int)fbold_v00.y2[t]);
-	    b.y3[t] = truncate256(b.y3[t] + (int)fbold_v00.y3[t]);
-	    b.y4[t] = truncate256(b.y4[t] + (int)fbold_v00.y4[t]);
-	    b.u[t] = truncate256(b.u[t] + (int)fbold_v00.u[t]);
-	    b.v[t] = truncate256(b.v[t] + (int)fbold_v00.v[t]);
-	}
-	copyblock(s, s->current, &b, bx, by);
-	return bits_v00;
-    } else {
-	/* i block (mode=3) */
-	mode = 3;
-	has_dc = 1;
-	memcpy(&b, &b_i, sizeof(block_t));
-	getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
-	swf_SetBits(tag,0,1); // COD
-	codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
-	codehuffman(tag, cbpy, cbpybits);
-
-	/* luminance */
-	encode8x8(tag, b.y1, has_dc, cbpybits&8);
-	encode8x8(tag, b.y2, has_dc, cbpybits&4);
-	encode8x8(tag, b.y3, has_dc, cbpybits&2);
-	encode8x8(tag, b.y4, has_dc, cbpybits&1);
-
-	/* chrominance */
-	encode8x8(tag, b.u, has_dc, cbpcbits&2);
-	encode8x8(tag, b.v, has_dc, cbpcbits&1);
-
-	/* -- reconstruction -- */
-	dequantize(&b, 1, *quant);
-	doidct(&b);
-	truncateblock(&b);
-	copyblock(s, s->current, &b, bx, by);
-	return bits_i;
+    codehuffman(tag, cbpy, y);
+
+    if(dquant) {
+	setQuant(tag, dquant);
     }
 
-    exit(1);
-#if 0
-    dodct(&fb);
-    quantize(&fb, &b, has_dc, *quant);
-    getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
+    /* luminance */
+    encode8x8(tag, b.y1, 1, y&8);
+    encode8x8(tag, b.y2, 1, y&4);
+    encode8x8(tag, b.y3, 1, y&2);
+    encode8x8(tag, b.y4, 1, y&1);
 
-    if(!dquant && has_mvd && !has_mvd24 && !has_dc) mode = 0;
-    else if(dquant && has_mvd && !has_mvd24 && !has_dc) mode = 1;
-    else if(!dquant && has_mvd && has_mvd24 && !has_dc) mode = 2;
-    else if(!dquant && !has_mvd && !has_mvd24 && has_dc) mode = 3;
-    else if(dquant && !has_mvd && !has_mvd24 && has_dc) mode = 4;
-    else exit(1);
+    /* chrominance */
+    encode8x8(tag, b.u, 1, c&2);
+    encode8x8(tag, b.v, 1, c&1);
 
-    swf_SetBits(tag,0,1); /* cod - 1 if we're not going to code this block*/
+    /* reconstruct */
+    dequantize(&b, 1, s->quant);
+    doidct(&b);
+    truncateblock(&b);
+    copyblock(s, s->current, &b, bx, by);
+}
+
+/*static void encode_blockI(TAG*tag, VIDEOSTREAM*s, int bx, int by)
+{
+    block_t fb;
+    block_t b;
+    iblockdata_t data;
+    int bits, quality;
+    int dquant = 0;
+    int cbpcbits = 0, cbpybits = 0;
 
-    codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
-    codehuffman(tag, cbpy, (mode==3 || mode==4)?cbpybits:cbpybits^15);
+    getregion(&fb, s->current, bx, by, s->width);
+    prepareIBlock(s, &data, bx, by, &fb, &bits, &quality);
+    
+    getblockpatterns(&data.b_i, &cbpybits, &cbpcbits, has_dc);
 
     if(dquant) {
-	setQuant(tag, dquant);
+	codehuffman(tag, mcbpc_intra, 4+cbpcbits);
+    } else {
+	codehuffman(tag, mcbpc_intra, 0+cbpcbits);
     }
 
-    if(has_mvd) {
-	/* 0,0 */
-	codehuffman(tag, mvd, 32);
-	codehuffman(tag, mvd, 32);
-    }
-    if(has_mvd24) {
+    codehuffman(tag, cbpy, cbpybits);
+
+    if(dquant) {
+	setQuant(tag, dquant);
     }
 
-    /* luminance */
-    encode8x8(tag, b.y1, has_dc, cbpybits&8);
-    encode8x8(tag, b.y2, has_dc, cbpybits&4);
-    encode8x8(tag, b.y3, has_dc, cbpybits&2);
-    encode8x8(tag, b.y4, has_dc, cbpybits&1);
+    // luminance
+    encode8x8(tag, b.y1, 1, cbpybits&8);
+    encode8x8(tag, b.y2, 1, cbpybits&4);
+    encode8x8(tag, b.y3, 1, cbpybits&2);
+    encode8x8(tag, b.y4, 1, cbpybits&1);
 
-    /* chrominance */
-    encode8x8(tag, b.u, has_dc, cbpcbits&2);
-    encode8x8(tag, b.v, has_dc, cbpcbits&1);
-#endif
-}
+    // chrominance
+    encode8x8(tag, b.u, 1, cbpcbits&2);
+    encode8x8(tag, b.v, 1, cbpcbits&1);
+
+    copyblock(s, s->current, &data->reconstruction, data->bx, data->by);
+}*/
 
 static int bmid = 0;
 void setdbgpic(TAG*tag, RGBA*pic, int width, int height)
@@ -1291,6 +1380,7 @@ void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
 
     if(quant<1) quant=1;
     if(quant>31) quant=31;
+    s->quant = quant;
 
     writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_IFRAME);
 
@@ -1303,7 +1393,7 @@ void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
     {
 	for(bx=0;bx<s->bbx;bx++)
 	{
-	    encode_blockI(tag, s, bx, by, &quant);
+	    encode_blockI(tag, s, bx, by);
 	}
     }
     s->frame++;
@@ -1316,6 +1406,7 @@ void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
 
     if(quant<1) quant=1;
     if(quant>31) quant=31;
+    s->quant = quant;
 
     writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_PFRAME);
 
@@ -1328,7 +1419,7 @@ void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
     {
 	for(bx=0;bx<s->bbx;bx++)
 	{
-	    encode_blockP(tag, s, bx, by, &quant);
+	    encode_blockP(tag, s, bx, by);
 	}
     }
     s->frame++;
@@ -1472,7 +1563,7 @@ int main(int argn, char*argv[])
     tag = swf_InsertTag(tag, ST_DEFINEVIDEOSTREAM);
     swf_SetU16(tag, 33);
     swf_SetVideoStreamDefine(tag, &stream, frames, width, height);
-    stream.do_motion = 1;
+    stream.do_motion = 0;
 
     for(t=0;t<frames;t++)
     {
@@ -1519,6 +1610,7 @@ int main(int argn, char*argv[])
     }
     close(fi);
     swf_FreeTags(&swf);
+    return 0;
 }
 #undef MAIN
 #endif