X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fh.263%2Fmkvideo.c;h=4046fc0f561620840441bb367bb564db28b2cfb3;hb=6da849f3320df43086c3d3cc01b162ea9c7dc847;hp=8fc554dcb8ddb491be5027c1ad76726ef4025d4b;hpb=958c6ff463beca74ae616d04a21e709f4a016855;p=swftools.git diff --git a/lib/h.263/mkvideo.c b/lib/h.263/mkvideo.c index 8fc554d..4046fc0 100644 --- a/lib/h.263/mkvideo.c +++ b/lib/h.263/mkvideo.c @@ -2,7 +2,7 @@ Create a video file. Part of the swftools package. - + Copyright (c) 2003 Matthias Kramm */ #include @@ -13,15 +13,20 @@ #include "h263tables.c" #include "swfvideo.h" +#ifdef MAIN +U16 totalframes = 0; +#endif void swf_SetVideoStreamDefine(TAG*tag, VIDEOSTREAM*stream, U16 frames, U16 width, U16 height) { - width=width&~15; height=height&~15; swf_SetU16(tag, frames); swf_SetU16(tag, width); swf_SetU16(tag, height); - swf_SetU8(tag, 1); /* smoothing on */ + //swf_SetU8(tag, 1); /* smoothing on */ + swf_SetU8(tag, 0); /* smoothing off */ swf_SetU8(tag, 2); /* codec = h.263 sorenson spark */ + totalframes = frames; + memset(stream, 0, sizeof(VIDEOSTREAM)); stream->olinex = width; width+=15;width&=~15; @@ -58,35 +63,24 @@ typedef struct _block_t int v[64]; } block_t; -typedef struct _fblock_t -{ - double y1[64]; - double y2[64]; - double y3[64]; - double y4[64]; - double u[64]; - double v[64]; -} fblock_t; - static int zigzagtable[64] = { - 0, 1, 5, 6, 14, 15, 27, 28, - 2, 4, 7, 13, 16, 26, 29, 42, - 3, 8, 12, 17, 25, 30, 41, 43, - 9, 11, 18, 24, 31, 40, 44, 53, - 10, 19, 23, 32, 39, 45, 52, 54, - 20, 22, 33, 38, 46, 51, 55, 60, - 21, 34, 37, 47, 50, 56, 59, 61, + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63}; -static void fzigzag(double*src) +static void zigzag(int*src) { - double tmp[64]; + int tmp[64]; int t; for(t=0;t<64;t++) { - ((int*)&tmp[zigzagtable[t]])[0] = ((int*)&src[t])[0]; - ((int*)&tmp[zigzagtable[t]])[1] = ((int*)&src[t])[1]; + tmp[zigzagtable[t]] = src[t]; } - memcpy(src, tmp, sizeof(double)*64); + memcpy(src, tmp, sizeof(int)*64); } #define PI 3.14159265358979 @@ -105,7 +99,7 @@ static double table[8][8] = {0.195090322016128,-0.555570233019602,0.831469612302545,-0.980785280403231,0.980785280403230,-0.831469612302545,0.555570233019602,-0.195090322016129} }; -static void dct(double*src) +static void dct(int*src) { double tmp[64]; int x,y,u,v,t; @@ -128,11 +122,11 @@ static void dct(double*src) { c+=table[v][y]*tmp[y*8+u]; } - src[v*8+u] = c*0.25; + src[v*8+u] = (int)(c*0.25+0.5); } } -static void idct(double*src) +static void idct(int*src) { double tmp[64]; int x,y,u,v; @@ -154,10 +148,100 @@ static void idct(double*src) { c+=table[v][y]*tmp[v*8+x]; } - src[y*8+x] = c*0.25; + src[y*8+x] = (int)(c*0.25+0.5); } } +static double c[8] = {1.0, +0.980785280403230, // cos(Pi*1/16), sin(Pi*7/16) +0.923879532511287, // cos(Pi*2/16), sin(Pi*6/16) +0.831469612302545, // cos(Pi*3/16), sin(Pi*5/16) +0.707106781186548, // cos(Pi*4/16), sin(Pi*4/16), 1/sqrt(2) +0.555570233019602, // cos(Pi*5/16), sin(Pi*3/16) +0.382683432365090, // cos(Pi*6/16), sin(Pi*2/16) +0.195090322016128 // cos(Pi*7/16), sin(Pi*1/16) +}; + +static double cc[8]; +int ccquant = -1; + +static void preparequant(int quant) +{ + if(ccquant == quant) + return; + cc[0] = c[0]/(quant*2*4); + cc[1] = c[1]/(quant*2*4); + cc[2] = c[2]/(quant*2*4); + cc[3] = c[3]/(quant*2*4); + cc[4] = c[4]/(quant*2*4); + cc[5] = c[5]/(quant*2*4); + cc[6] = c[6]/(quant*2*4); + cc[7] = c[7]/(quant*2*4); + ccquant = quant; +} + +inline static void innerdct(double*a,double*b, double*c) +{ + // c1*c7*2 = c6 + // c2*c6*2 = c4 + // c3*c5*2 = c2 + // c4*c4*2 = 1 + + //{ 1, 3, 5, 7, -7, -5, -3, -1}, + //{ 3, -7, -1, -5, 5, 1, 7, -3}, + //{ 5, -1, 7, 3, -3, -7, 1, -5}, + //{ 7, -5, 3, -1, 1, -3, 5, -7} + double b0,b1,b2,b3,b4,b5; + b2 = (a[0]+a[7]); + b3 = (a[1]+a[6]); + b4 = (a[2]+a[5]); + b5 = (a[3]+a[4]); + + b0 = (b2+b5)*c[4]; + b1 = (b3+b4)*c[4]; + b[0*8] = b0 + b1; + b[4*8] = b0 - b1; + b[2*8] = (b2-b5)*c[2] + (b3-b4)*c[6]; + b[6*8] = (b2-b5)*c[6] + (b4-b3)*c[2]; + + b0 = (a[0]-a[7]); + b1 = (a[1]-a[6]); + b2 = (a[2]-a[5]); + b3 = (a[3]-a[4]); + + b[1*8] = b0*c[1] + b1*c[3] + b2*c[5] + b3*c[7]; + b[3*8] = b0*c[3] - b1*c[7] - b2*c[1] - b3*c[5]; + b[5*8] = b0*c[5] - b1*c[1] + b2*c[7] + b3*c[3]; + b[7*8] = b0*c[7] - b1*c[5] + b2*c[3] - b3*c[1]; +} + +static void dct2(int*src, int*dest) +{ + double tmp[64], tmp2[64]; + double*p; + int u,x,v,t; + + for(t=0;t<64;t++) + tmp2[t] = src[t]; + + for(v=0;v<8;v++) + { + double* a=&tmp2[v*8]; + double* b=&tmp[v]; + innerdct(a,b,c); + } + for(v=0;v<8;v++) + { + double* a=&tmp[v*8]; + double* b=&tmp2[v]; + innerdct(a,b,cc); + } + for(t=0;t<64;t++) { + dest[zigzagtable[t]] = (int)(tmp2[t]); + } +} + + static inline int truncate256(int a) { if(a>255) return 255; @@ -165,13 +249,17 @@ static inline int truncate256(int a) return a; } -static void getregion(fblock_t* bb, YUV*pic, int posx, int posy, int linex) +static void getregion(block_t* bb, YUV*pic, int posx, int posy, int linex) { - YUV*p1 = &pic[posy*linex+posx]; - YUV*p2 = p1; + YUV*p1; + YUV*p2; int y1=0, y2=0, y3=0, y4=0; int u=0,v=0; int x,y; + posx*=16; + posy*=16; + p1 = &pic[posy*linex+posx]; + p2 = p1; for(y=0;y<8;y++) { for(x=0;x<8;x++) { bb->u[u++] = (p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4; @@ -185,6 +273,125 @@ static void getregion(fblock_t* bb, YUV*pic, int posx, int posy, int linex) p2+=linex*2; } } + +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; @@ -197,6 +404,8 @@ static void rgb2yuv(YUV*dest, RGBA*src, int dlinex, int slinex, int width, int h /*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; @@ -238,16 +447,16 @@ static void copyblock(VIDEOSTREAM*s, YUV*dest, block_t*b, int bx, int by) 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].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].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].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].v = b->v[(y/2+4)*8+(x/2)+4]; p2[x+8].y = b->y4[y*8+x]; } p1+=s->linex; @@ -321,7 +530,7 @@ static int codehuffman(TAG*tag, struct huffcode*table, int index) return i; } -static void quantize8x8(double*src, int*dest, int has_dc, int quant) +static void quantize8x8(int*src, int*dest, int has_dc, int quant) { int t,pos=0; double q = 1.0/(quant*2); @@ -504,22 +713,43 @@ static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef) } } -static void dodct(fblock_t*fb) +static void quantize(block_t*fb, block_t*b, int has_dc, int quant) +{ + quantize8x8(fb->y1, b->y1, has_dc, quant); + quantize8x8(fb->y2, b->y2, has_dc, quant); + quantize8x8(fb->y3, b->y3, has_dc, quant); + quantize8x8(fb->y4, b->y4, has_dc, quant); + quantize8x8(fb->u, b->u, has_dc, quant); + quantize8x8(fb->v, b->v, has_dc, quant); +} + +static void dodct(block_t*fb) +{ + dct(fb->y1); dct(fb->y2); dct(fb->y3); dct(fb->y4); + dct(fb->u); dct(fb->v); + zigzag(fb->y1); + zigzag(fb->y2); + zigzag(fb->y3); + zigzag(fb->y4); + zigzag(fb->u); + zigzag(fb->v); +} +static void dodctandquant(block_t*fb, block_t*b, int has_dc, int quant) { int t; - dct(fb->y1); dct(fb->y2); dct(fb->y3); dct(fb->y4); - dct(fb->u); dct(fb->v); - fzigzag(fb->y1); - fzigzag(fb->y2); - fzigzag(fb->y3); - fzigzag(fb->y4); - fzigzag(fb->u); - fzigzag(fb->v); + if(has_dc) { + dodct(fb); + quantize(fb,b,has_dc,quant); + return; + } + preparequant(quant); + dct2(fb->y1,b->y1); dct2(fb->y2,b->y2); dct2(fb->y3,b->y3); dct2(fb->y4,b->y4); + dct2(fb->u,b->u); dct2(fb->v,b->v); } static void doidct(block_t*b) { - fblock_t fb; + block_t fb; int t; for(t=0;t<64;t++) { fb.y1[t] = b->y1[zigzagtable[t]]; @@ -529,8 +759,8 @@ static void doidct(block_t*b) fb.u[t] = b->u[zigzagtable[t]]; fb.v[t] = b->v[zigzagtable[t]]; } - idct(fb.y1); idct(fb.y2); idct(fb.y3); idct(fb.y4); - idct(fb.u); idct(fb.v); + idct(fb.y1); idct(fb.y2); idct(fb.y3); idct(fb.y4); + idct(fb.u); idct(fb.v); for(t=0;t<64;t++) { b->y1[t] = fb.y1[t]; b->y2[t] = fb.y2[t]; @@ -553,23 +783,14 @@ static void truncateblock(block_t*b) } } -static void quantize(fblock_t*fb, block_t*b, int has_dc, int quant) -{ - quantize8x8(fb->y1, b->y1, has_dc, quant); - quantize8x8(fb->y2, b->y2, has_dc, quant); - quantize8x8(fb->y3, b->y3, has_dc, quant); - quantize8x8(fb->y4, b->y4, has_dc, quant); - quantize8x8(fb->u, b->u, has_dc, quant); - quantize8x8(fb->v, b->v, has_dc, quant); -} static void dequantize(block_t*b, int has_dc, int quant) { - dequantize8x8(b->y1, has_dc, quant); - dequantize8x8(b->y2, has_dc, quant); - dequantize8x8(b->y3, has_dc, quant); - dequantize8x8(b->y4, has_dc, quant); - dequantize8x8(b->u, has_dc, quant); - dequantize8x8(b->v, has_dc, quant); + dequantize8x8(b->y1, has_dc, quant); + dequantize8x8(b->y2, has_dc, quant); + dequantize8x8(b->y3, has_dc, quant); + dequantize8x8(b->y4, has_dc, quant); + dequantize8x8(b->u, has_dc, quant); + dequantize8x8(b->v, has_dc, quant); } static void getblockpatterns(block_t*b, int*cbpybits,int*cbpcbits, int has_dc) @@ -613,17 +834,18 @@ static void change_quant(int quant, int*dquant) static void encode_blockI(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) { - fblock_t fb; + block_t fb; block_t b; int dquant=0; int cbpcbits = 0, cbpybits=0; - getregion(&fb, s->current, bx*16, by*16, s->width); - dodct(&fb); - + getregion(&fb, s->current, bx, by, s->width); + change_quant(*quant, &dquant); *quant+=dquant; - quantize(&fb, &b, 1, *quant); + + dodctandquant(&fb, &b, 1, *quant); + //quantize(&fb, &b, 1, *quant); //decode_blockI(s, &b, bx, by); @@ -658,7 +880,7 @@ static void encode_blockI(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) copyblock(s, s->current, &b, bx, by); } -static void yuvdiff(fblock_t*a, fblock_t*b) +static void yuvdiff(block_t*a, block_t*b) { int t; for(t=0;t<64;t++) { @@ -684,14 +906,14 @@ static void predictmvd(VIDEOSTREAM*s, int bx, int by, int*px, int*py) y2=s->mvdy[(by-1)*s->bbx+bx]; if(bxbbx-1) { x3=s->mvdx[(by-1)*s->bbx+bx+1]; - y3=s->mvdy[(by-1)*s->bbx+bx+1]; + y3=s->mvdy[(by-1)*s->bbx+bx+1]; } else { x3=y3=0; } } else {x2=x3=x1;y2=y3=y1;} - if((x1 <= x2 && x2 <= x3) || + if((x1 <= x2 && x2 <= x3) || (x3 <= x2 && x2 <= x1)) { x4=x2; } else if((x2 <= x1 && x1 <= x3) || @@ -702,7 +924,7 @@ static void predictmvd(VIDEOSTREAM*s, int bx, int by, int*px, int*py) x4=x3; } - if((y1 <= y2 && y2 <= y3) || + if((y1 <= y2 && y2 <= y3) || (y3 <= y2 && y2 <= y1)) { y4=y2; } else if((y2 <= y1 && y1 <= y3) || @@ -721,9 +943,9 @@ static void predictmvd(VIDEOSTREAM*s, int bx, int by, int*px, int*py) static inline int mvd2index(int px, int py, int x, int y, int xy) { assert((x>=-32 && x<=31) && (y>=-32 && y<=31)); - assert((x&1)==0 && (y&1)==0);//for now - assert((x&2)==0 && (y&2)==0);//for now(2) - + //assert((x&1)==0 && (y&1)==0);//for now + //assert((x&2)==0 && (y&2)==0);//for now(2) + x-=px; y-=py; @@ -743,7 +965,7 @@ static inline int mvd2index(int px, int py, int x, int y, int xy) static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) { - fblock_t fb; + block_t fb; block_t b; int dquant=0; int has_mvd=0; @@ -758,14 +980,17 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) block_t b_i; int bits_i; - fblock_t fbold_v00; + block_t fbold_v00; block_t b_v00; int bits_v00 = 65535; int x_v00=0; int y_v00=0; diff = compareregions(s, bx, by); + if(diff < 20 /*TODO: should be a parameter- good values are between 32 and 48 */) { + /* TODO: measure the error an I-block encoding would do, and base the decision + on that */ 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); @@ -773,14 +998,14 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) } predictmvd(s,bx,by,&predictmvdx,&predictmvdy); - getregion(&fb, s->current, bx*16, by*16, s->width); + getregion(&fb, s->current, bx, by, s->width); { /* consider I-block */ - fblock_t fb_i; + block_t fb_i; int y,c; - memcpy(&fb_i, &fb, sizeof(fblock_t)); - dodct(&fb_i); - quantize(&fb_i, &b_i, 1, *quant); + 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; @@ -793,9 +1018,8 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) bits_i += coefbits8x8(b_i.v, 1); } - if(bx&&by&&(bxbbx-1)&&(bybby-1)) { /* consider mvd(x,y)-block */ - fblock_t fbdiff; + block_t fbdiff; int y,c; x_v00=0; @@ -804,18 +1028,25 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) if(s->do_motion) { int hx,hy; int bestx=0,besty=0,bestbits=65536; + int startx=-2,endx=2; + int starty=-2,endy=2; + + if(!bx) startx=0; + if(!by) starty=0; + if(bx==s->bbx-1) endx=0; + if(by==s->bby-1) endy=0; - for(hx=-8;hx<8;hx+=4) - for(hy=-8;hy<8;hy+=4) + for(hx=startx;hx<=endx;hx+=1) + for(hy=starty;hy<=endy;hy+=1) { block_t b; - fblock_t fbold; + block_t fbold; int bits = 0; - memcpy(&fbdiff, &fb, sizeof(fblock_t)); - getregion(&fbold, s->oldpic, bx*16+hx/2, by*16+hy/2, s->linex); + memcpy(&fbdiff, &fb, sizeof(block_t)); + getmvdregion(&fbold, s->oldpic, bx, by, hx, hy, s->linex); yuvdiff(&fbdiff, &fbold); - dodct(&fbdiff); - quantize(&fbdiff, &b, 0, *quant); + 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); @@ -832,11 +1063,11 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) y_v00 = besty; } - memcpy(&fbdiff, &fb, sizeof(fblock_t)); - getregion(&fbold_v00, s->oldpic, bx*16+x_v00/2, by*16+y_v00/2, s->linex); + memcpy(&fbdiff, &fb, sizeof(block_t)); + getmvdregion(&fbold_v00, s->oldpic, bx, by, x_v00, y_v00, s->linex); yuvdiff(&fbdiff, &fbold_v00); - dodct(&fbdiff); - quantize(&fbdiff, &b_v00, 0, *quant); + dodctandquant(&fbdiff, &b_v00, 0, *quant); + //quantize(&fbdiff, &b_v00, 0, *quant); getblockpatterns(&b_v00, &y, &c, 0); bits_v00 = 1; //cod @@ -853,7 +1084,7 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) } if(bits_i > bits_v00) - { + { /* mvd (0,0) block (mode=0) */ int t; mode = 0; // mvd w/o mvd24 @@ -867,7 +1098,7 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) /* vector */ codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 0)); - codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 1)); + 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; @@ -880,7 +1111,7 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) /* chrominance */ encode8x8(tag, b.u, has_dc, cbpcbits&2); encode8x8(tag, b.v, has_dc, cbpcbits&1); - + /* -- reconstruction -- */ dequantize(&b, 0, *quant); doidct(&b); @@ -936,7 +1167,7 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) else exit(1); swf_SetBits(tag,0,1); /* cod - 1 if we're not going to code this block*/ - + codehuffman(tag, mcbpc_inter, mode*4+cbpcbits); codehuffman(tag, cbpy, (mode==3 || mode==4)?cbpybits:cbpybits^15); @@ -964,6 +1195,31 @@ static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant) #endif } +static int bmid = 0; +void setdbgpic(TAG*tag, RGBA*pic, int width, int height) +{ + MATRIX m; + tag = tag->prev; + + tag = swf_InsertTag(tag,ST_REMOVEOBJECT2); + swf_SetU16(tag, 133); + + tag = swf_InsertTag(tag, ST_DEFINEBITSLOSSLESS); + swf_SetU16(tag, 1000+bmid); + swf_SetLosslessBits(tag, width, height, (void*)pic, BMF_32BIT); + + tag = swf_InsertTag(tag, ST_DEFINESHAPE); + swf_SetU16(tag, 2000+bmid); + swf_ShapeSetBitmapRect(tag, 1000+bmid, width, height); + + tag = swf_InsertTag(tag,ST_PLACEOBJECT2); + swf_GetMatrix(0,&m); + m.tx = width*20; + swf_ObjectPlace(tag, 2000+bmid, 133, &m, 0, 0); + + bmid++; +} + #define TYPE_IFRAME 0 #define TYPE_PFRAME 1 @@ -1004,200 +1260,6 @@ static void writeHeader(TAG*tag, int width, int height, int frame, int quant, in swf_SetBits(tag, 0, 1); /* No extra info */ } -int stat_qdiff(double*b1, double*b2) -{ - int x; - double diff=0; - for(x=0;x<64;x++) { - double y1 = b1[x] - b2[x]; - diff += y1*y1; - } - return (int)(diff/64); -} - -int stat_absdiff(double*b1, double*b2) -{ - int x; - double diff=0; - for(x=0;x<64;x++) { - double y1 = b1[x] - b2[x]; - diff += fabs(y1); - } - return (int)(diff/64); -} - -int stat_absfreq(double*b1, double*b2) -{ - int x; - double diff=0; - double d1[64],d2[64]; - memcpy(&d1, b1, 64*sizeof(double)); - dct(d1); - memcpy(&d2, b2, 64*sizeof(double)); - dct(d2); - for(x=0;x<64;x++) { - double y1 = d1[x] - d2[x]; - diff += fabs(y1); - } - return (int)(diff/64); -} - -int stat_qfreq(double*b1, double*b2) -{ - int x; - double diff=0; - double d1[64],d2[64]; - memcpy(&d1, b1, 64*sizeof(double)); - dct(d1); - memcpy(&d2, b2, 64*sizeof(double)); - dct(d2); - for(x=0;x<64;x++) { - double y1 = d1[x] - d2[x]; - diff += y1*y1; - } - return (int)(diff/64); -} - -int stat_nonnull(double*b1, double*b2) -{ - int x; - int diff=0; - double d1[64],d2[64]; - memcpy(&d1, b1, 64*sizeof(double)); - dct(d1); - memcpy(&d2, b2, 64*sizeof(double)); - dct(d2); - for(x=0;x<64;x++) { - int y1 = (int)((d1[x] - d2[x])/9); - if(y1) - diff++; - } - return diff; -} - -void stat_filter(FILE*fi, double*d1, double*d2) -{ - int x,y,xx,yy,b; - for(b=3;b>=0;b--) { - int d = 1<=0;b--) { - int d = 1<=0;b--) { - int d = 1<bby;by++) - for(bx=0;bxbbx;bx++) - { - for(by2=0;by2bby;by2++) - for(bx2=0;bx2current, bx*16, by*16, s->linex); - memcpy(&fbdiff, &fbnew, sizeof(fblock_t)); - getregion(&fbold, s->current, bx2*16, by2*16, s->linex); - yuvdiff(&fbdiff, &fbold); - dodct(&fbdiff); - quantize(&fbdiff, &b, 0, quant); - - stat(fi, b.y1, fbnew.y1, fbold.y1); - stat(fi, b.y2, fbnew.y2, fbold.y2); - stat(fi, b.y3, fbnew.y3, fbold.y3); - stat(fi, b.y4, fbnew.y4, fbold.y4); - stat(fi, b.u, fbnew.u, fbold.u); - stat(fi, b.v, fbnew.v, fbold.v); - - num++; - if(num==1000) { - fclose(fi); - exit(7); - } - } - printf("%d\n", num);fflush(stdout); - } - fclose(fi); - exit(7); -} - void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant) { int bx, by; @@ -1244,11 +1306,17 @@ void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant) } s->frame++; memcpy(s->oldpic, s->current, s->width*s->height*sizeof(YUV)); + +//#define PNG #ifdef MAIN +#ifdef PNG + yuv2rgb(pic, s->current, s->linex, s->width, s->height); + setdbgpic(tag, pic, s->width, s->height); +#endif + if(s->frame == (int)totalframes-1) { int t; FILE*fi = fopen("test.ppm", "wb"); - yuv2rgb(pic, s->current, s->linex, s->width, s->height); fprintf(fi, "P6\n%d %d\n255\n", s->width, s->height); for(t=0;twidth*s->height;t++) { @@ -1261,6 +1329,77 @@ void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant) #endif } +int uline[64],vline[64],yline[64]; +void swf_SetVideoStreamMover(TAG*tag, VIDEOSTREAM*s, int quant) +{ + int bx, by; + + if(quant<1) quant=1; + if(quant>31) quant=31; + + writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_PFRAME); + + memset(s->mvdx, 0, s->bbx*s->bby*sizeof(int)); + memset(s->mvdy, 0, s->bbx*s->bby*sizeof(int)); + + for(by=0;bybby;by++) + { + for(bx=0;bxbbx;bx++) + { + //if((lrand48()&255) || !(bx>8 && bx<24 && by>8 && by<24)) { + if(!(by==31)) { + /* mvd (0,0) block (mode=0) */ + int t; + int mode = 0; // mvd w/o mvd24 + int has_dc = 0; + int cbpybits=0,cbpcbits=0; + int predictmvdx, predictmvdy; + //int mvx=-1+(2*(s->frame&1)); + //int mvy=-1+((s->frame&2)); + int mvx=(lrand48()%4)-2; + int mvy=3; + + swf_SetBits(tag,0,1); // COD + codehuffman(tag, mcbpc_inter, mode*4+cbpcbits); + codehuffman(tag, cbpy, cbpybits^15); + + /* vector */ + predictmvd(s,bx,by,&predictmvdx,&predictmvdy); + codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, mvx, mvy, 0)); + codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, mvx, mvy, 1)); + s->mvdx[by*s->bbx+bx] = mvx; + s->mvdy[by*s->bbx+bx] = mvy; + } else { + /* i block (mode=3) */ + int mode = 3; + int has_dc = 1; + int cbpybits,cbpcbits; + int t; + block_t b; + memset(&b, 0, sizeof(block_t)); + b.y1[0] = b.y2[0] = b.y3[0] = b.y4[0] = yline[bx]; + b.u[0] = uline[bx]; + b.v[0] = vline[bx]; + + 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); + } + } + } +} + #ifdef MAIN #include "png.h" int main(int argn, char*argv[]) @@ -1273,7 +1412,7 @@ int main(int argn, char*argv[]) SWFPLACEOBJECT obj; int width = 0; int height = 0; - int frames = 50; + int frames = 20; int framerate = 29; unsigned char*data; char* fname = "/home/kramm/pics/peppers.png"; @@ -1295,8 +1434,8 @@ int main(int argn, char*argv[]) swf.fileVersion = 6; swf.frameRate = framerate*256; - swf.movieSize.xmax = 20*width; - swf.movieSize.ymax = 20*height; + swf.movieSize.xmax = 20*width*2; + swf.movieSize.ymax = 20*height-20*64; swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); tag = swf.firstTag; @@ -1307,7 +1446,7 @@ int main(int argn, char*argv[]) swf_SetU16(tag, 33); swf_SetVideoStreamDefine(tag, &stream, frames, width, height); stream.do_motion = 1; - + for(t=0;t