X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fh.263%2Fmkvideo.c;h=db8d5278b24826aeb69f0debafb761abcb363070;hb=a7a60c127b70f891c5bb1ecf58b9e90dfbfb1e41;hp=ebe859ab24a2569e9480109842e021f219bcbe0c;hpb=bac2af381e6c670485d9792d893f39a3df429ab9;p=swftools.git diff --git a/lib/h.263/mkvideo.c b/lib/h.263/mkvideo.c index ebe859a..db8d527 100644 --- a/lib/h.263/mkvideo.c +++ b/lib/h.263/mkvideo.c @@ -9,24 +9,9 @@ #include #include #include -#include "../lib/rfxswf.h" -#include "png.h" +#include "../rfxswf.h" #include "h263tables.c" - -typedef struct _YUV -{ - unsigned char y,u,v; -} YUV; - -typedef struct _VIDEOSTREAM -{ - int width; - int height; - int frame; - int linex; - YUV*oldpic; - YUV*current; -} VIDEOSTREAM; +#include "swfvideo.h" void swf_SetVideoStreamDefine(TAG*tag, VIDEOSTREAM*stream, U16 frames, U16 width, U16 height) { @@ -38,15 +23,22 @@ void swf_SetVideoStreamDefine(TAG*tag, VIDEOSTREAM*stream, U16 frames, U16 width swf_SetU8(tag, 2); /* codec = h.263 sorenson spark */ memset(stream, 0, sizeof(VIDEOSTREAM)); + stream->olinex = width; + width+=15;width&=~15; + height+=15;height&=~15; stream->linex = width; - width&=~15; - height&=~15; stream->width = width; stream->height = height; stream->current = (YUV*)malloc(width*height*sizeof(YUV)); stream->oldpic = (YUV*)malloc(width*height*sizeof(YUV)); memset(stream->oldpic, 0, width*height*sizeof(YUV)); + memset(stream->current, 0, width*height*sizeof(YUV)); +} +void swf_VideoStreamClear(VIDEOSTREAM*stream) +{ + free(stream->oldpic);stream->oldpic = 0; + free(stream->current);stream->current = 0; } typedef struct _block_t @@ -186,18 +178,21 @@ static void getregion(fblock_t* bb, YUV*pic, int bx, int by, int linex) p2+=linex*2; } } -static void rgb2yuv(YUV*dest, RGBA*src, int linex, int width, int height) +static void rgb2yuv(YUV*dest, RGBA*src, int dlinex, int slinex, int width, int height) { int x,y; for(y=0;y>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; } } } @@ -275,7 +270,7 @@ static int compareregions(VIDEOSTREAM*s, int bx, int by) return diff/256; } -static int valtodc(int val) +static inline int valtodc(int val) { assert(val>=0); @@ -322,16 +317,21 @@ static int codehuffman(TAG*tag, struct huffcode*table, int index) static void quantize8x8(double*src, int*dest, int has_dc, int quant) { int t,pos=0; + double q = 1.0/(quant*2); if(has_dc) { dest[0] = valtodc((int)src[0]); /*DC*/ pos++; } for(t=pos;t<64;t++) { - dest[t] = (int)src[t]; + //dest[t] = (int)src[t]; /* exact: if(quant&1){dest[t] = (dest[t]/quant - 1)/2;}else{dest[t] = ((dest[t]+1)/quant - 1)/2;} */ //if(quant&1){dest[t] = (dest[t]/quant - 1)/2;}else{dest[t] = ((dest[t]+1)/quant - 1)/2;} - dest[t] = dest[t]/(quant*2); + //dest[t] = dest[t]/(quant*2); + dest[t] = (int)(src[t]*q); + /* TODO: warn if this happens- the video will be buggy */ + if(dest[t]>127) dest[t]=127; + if(dest[t]<-127) dest[t]=-127; } } @@ -379,10 +379,57 @@ static int hascoef(int*b, int has_dc) return 0; } +static int coefbits8x8(int*bb, int has_dc) +{ + int t; + int pos=0; + int bits=0; + int last; + + if(has_dc) { + bits+=8; + pos++; + } + for(last=63;last>=pos;last--) { + if(bb[last]) + break; + } + if(last < pos) + return bits; + while(1) { + int run=0, level=0, islast=0,t; + while(!bb[pos] && poscurrent, s->oldpic, bx, by); - return; + return 1; } getregion(&fb, s->current, bx, by, s->width); - //if(diff < 128) - if(1) + { /* consider I-block */ + fblock_t fb_i; + int y,c; + memcpy(&fb_i, &fb, sizeof(fblock_t)); + dodct(&fb_i); + 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); + } + + { /* consider mvd(0,0)-block */ + fblock_t fbdiff; + int y,c; + memcpy(&fbdiff, &fb, sizeof(fblock_t)); + getregion(&fbold_v00, s->oldpic, bx, by, s->linex); + yuvdiff(&fbdiff, &fbold_v00); + dodct(&fbdiff); + 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[32].len; // (0,0) + bits_v00 += mvd[32].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(bits_i > bits_v00) { /* mvd (0,0) block (mode=0) */ int t; - memcpy(&fbdiff, &fb, sizeof(fblock_t)); - getregion(&fbold, s->oldpic, bx, by, s->linex); - yuvdiff(&fbdiff, &fbold); - //getregiondiff(&fbdiff, s->oldpic, s->current, bx, by, s->linex); - dodct(&fbdiff); + mode = 0; // mvd w/o mvd24 has_dc = 0; + memcpy(&b, &b_v00, sizeof(block_t)); - quantize(&fbdiff, &b, has_dc, *quant); getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc); - mode = 0; // mvd w/o mvd24 swf_SetBits(tag,0,1); // COD codehuffman(tag, mcbpc_inter, mode*4+cbpcbits); codehuffman(tag, cbpy, cbpybits^15); @@ -669,27 +758,27 @@ static void 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); for(t=0;t<64;t++) { - b.y1[t] = truncate256(b.y1[t] + (int)fbold.y1[t]); - b.y2[t] = truncate256(b.y2[t] + (int)fbold.y2[t]); - b.y3[t] = truncate256(b.y3[t] + (int)fbold.y3[t]); - b.y4[t] = truncate256(b.y4[t] + (int)fbold.y4[t]); - b.u[t] = truncate256(b.u[t] + (int)fbold.u[t]); - b.v[t] = truncate256(b.v[t] + (int)fbold.v[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; + return bits_v00; } else { /* i block (mode=3) */ mode = 3; has_dc = 1; - dodct(&fb); - quantize(&fb, &b, has_dc, *quant); + memcpy(&b, &b_i, sizeof(block_t)); + //dodct(&fb); + //quantize(&fb, &b, has_dc, *quant); getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc); swf_SetBits(tag,0,1); // COD codehuffman(tag, mcbpc_inter, mode*4+cbpcbits); @@ -704,12 +793,13 @@ static void 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, 1, *quant); doidct(&b); truncateblock(&b); copyblock(s, s->current, &b, bx, by); - return; + return bits_i; } exit(1); @@ -794,17 +884,19 @@ static void writeHeader(TAG*tag, int width, int height, int frame, int quant, in swf_SetBits(tag, 0, 1); /* No extra info */ } -void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic) +void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant) { int bx, by, bbx, bby; - int quant = 3; + + if(quant<1) quant=1; + if(quant>31) quant=31; writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_IFRAME); bbx = (s->width+15)/16; //TODO: move bbx,bby into VIDEOSTREAM bby = (s->height+15)/16; - rgb2yuv(s->current, pic, s->linex, s->width, s->height); + rgb2yuv(s->current, pic, s->linex, s->olinex, s->width, s->height); for(by=0;byoldpic, s->current, s->width*s->height*sizeof(YUV)); } -void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic) +void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant) { int bx, by, bbx, bby; - int quant = 3; + + if(quant<1) quant=1; + if(quant>31) quant=31; writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_PFRAME); bbx = (s->width+15)/16; bby = (s->height+15)/16; - rgb2yuv(s->current, pic, s->linex, s->width, s->height); + rgb2yuv(s->current, pic, s->linex, s->olinex, s->width, s->height); for(by=0;by