renamed png functions
[swftools.git] / lib / h.263 / swfvideo.c
index 6e21494..d9e1803 100644 (file)
@@ -37,13 +37,6 @@ U16 totalframes = 0;
 #endif
 void swf_SetVideoStreamDefine(TAG*tag, VIDEOSTREAM*stream, U16 frames, U16 width, U16 height)
 {
-    swf_SetU16(tag, frames);
-    swf_SetU16(tag, width);
-    swf_SetU16(tag, height);
-    //swf_SetU8(tag, 1); /* smoothing on */
-    swf_SetU8(tag, 0); /* smoothing off */
-    swf_SetU8(tag, 2); /* codec = h.263 sorenson spark */
-
 #ifdef MAIN
     totalframes = frames;
 #endif
@@ -58,26 +51,31 @@ void swf_SetVideoStreamDefine(TAG*tag, VIDEOSTREAM*stream, U16 frames, U16 width
     stream->height = height;
     stream->bbx = width/16;
     stream->bby = height/16;
-    stream->current = (YUV*)malloc(width*height*sizeof(YUV));
-    stream->oldpic = (YUV*)malloc(width*height*sizeof(YUV));
-    stream->mvdx = (int*)malloc(stream->bbx*stream->bby*sizeof(int));
-    stream->mvdy = (int*)malloc(stream->bbx*stream->bby*sizeof(int));
+    stream->current = (YUV*)rfx_calloc(width*height*sizeof(YUV));
+    stream->oldpic = (YUV*)rfx_calloc(width*height*sizeof(YUV));
+    stream->mvdx = (int*)rfx_alloc(stream->bbx*stream->bby*sizeof(int));
+    stream->mvdy = (int*)rfx_alloc(stream->bbx*stream->bby*sizeof(int));
     stream->do_motion = 0;
 
-    memset(stream->oldpic, 0, width*height*sizeof(YUV));
-    memset(stream->current, 0, width*height*sizeof(YUV));
-
     assert((stream->width&15) == 0);
     assert((stream->height&15) == 0);
     assert((stream->bbx*16) == stream->width);
     assert((stream->bby*16) == stream->height);
+    
+    swf_SetU16(tag, frames);
+    swf_SetU16(tag, width);
+    swf_SetU16(tag, height);
+    //swf_SetU8(tag, 1); /* smoothing on */
+    swf_SetU8(tag, 0); /* smoothing off */
+    swf_SetU8(tag, 2); /* codec = h.263 sorenson spark */
+
 }
 void swf_VideoStreamClear(VIDEOSTREAM*stream)
 {
-    free(stream->oldpic);stream->oldpic = 0;
-    free(stream->current);stream->current = 0;
-    free(stream->mvdx);stream->mvdx=0;
-    free(stream->mvdy);stream->mvdy=0;
+    rfx_free(stream->oldpic);stream->oldpic = 0;
+    rfx_free(stream->current);stream->current = 0;
+    rfx_free(stream->mvdx);stream->mvdx=0;
+    rfx_free(stream->mvdy);stream->mvdy=0;
 }
 
 typedef struct _block_t
@@ -255,6 +253,7 @@ static void rgb2yuv(YUV*dest, RGBA*src, int dlinex, int slinex, int width, int h
            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;
@@ -597,9 +596,15 @@ static int encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
                bits += codehuffman(tag, rle, RLE_ESCAPE);
                level=bb[pos];
                /* table 14/h.263 */
+               if(!level || level<-127 || level>127) {
+                   fprintf(stderr, "Warning: Overflow- Level %d at pos %d\n", level, pos);
+                   if(level<-127) level=-127;
+                   if(level>127) level=127;
+               }
+
                assert(level);
                assert(level>=-127);
-               assert(level<=127);
+               assert(level<=127); //TODO: known to fail for pos=0 (with custom frames?)
 
                swf_SetBits(tag, islast, 1);
                swf_SetBits(tag, run, 6);
@@ -816,6 +821,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)
 {
+
+    if((x<-32 && x>31) || (y<-32 && y>31)) 
+       fprintf(stderr, "(%d,%d)\n", x,y);
     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)
@@ -1055,9 +1063,9 @@ void prepareMVDBlock(VIDEOSTREAM*s, mvdblockdata_t*data, int bx, int by, block_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
+    /* mvd (0,0) block (mode=0) */
     int mode = 0;
     int bx = data->bx;
     int by = data->by;
@@ -1229,6 +1237,38 @@ void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
     s->frame++;
     memcpy(s->oldpic, s->current, s->width*s->height*sizeof(YUV));
 }
+void swf_SetVideoStreamBlackFrame(TAG*tag, VIDEOSTREAM*s)
+{
+    int bx, by;
+    int quant = 31;
+    int x,y;
+    s->quant = quant;
+
+    writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_IFRAME);
+
+    for(y=0;y<s->height;y++)
+    for(x=0;x<s->width;x++) {
+       s->current[y*s->width+x].y = 0;
+       s->current[y*s->width+x].u = 128;
+       s->current[y*s->width+x].v = 128;
+    }
+    for(x=0;x<16;x++)
+    for(y=0;y<16;y++) {
+       s->current[y*s->width+x].y = 64; 
+       s->current[y*s->width+x].u = 128; 
+       s->current[y*s->width+x].v = 128;
+    }
+
+    for(by=0;by<s->bby;by++)
+    {
+       for(bx=0;bx<s->bbx;bx++)
+       {
+           encode_IFrame_block(tag, s, bx, by);
+       }
+    }
+    s->frame++;
+    memcpy(s->oldpic, s->current, s->width*s->height*sizeof(YUV));
+}
 
 void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
 {
@@ -1265,12 +1305,14 @@ void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
 #endif
 }
 
-void swf_SetVideoStreamMover(TAG*tag, VIDEOSTREAM*s, signed char* movex, signed char* movey, int quant)
+void swf_SetVideoStreamMover(TAG*tag, VIDEOSTREAM*s, signed char* movex, signed char* movey, void**pictures, int quant)
 {
     int bx, by;
+    YUV pic[16*16];
 
     if(quant<1) quant=1;
     if(quant>31) quant=31;
+    s->quant = quant;
 
     writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_PFRAME);
 
@@ -1281,29 +1323,67 @@ void swf_SetVideoStreamMover(TAG*tag, VIDEOSTREAM*s, signed char* movex, signed
     {
        for(bx=0;bx<s->bbx;bx++)
        {
-           if(!(by==31)) {
-               /* mvd (0,0) block (mode=0) */
-               int t;
-               int mode = 0;
-               int has_dc = 0;
-               int cbpybits=0,cbpcbits=0;
-               int predictmvdx, predictmvdy;
-               int mvx=movex[by*s->bbx+bx];
-               int mvy=movey[by*s->bbx+bx];
+           int predictmvdx=0, predictmvdy=0;
+           int mvx=movex[by*s->bbx+bx];
+           int mvy=movey[by*s->bbx+bx];
+           void*picture = pictures?pictures[by*s->bbx+bx]:0;
+    
+           if(mvx<-32) mvx=-32;
+           if(mvx>31) mvx=31;
+           if(mvy<-32) mvy=-32;
+           if(mvy>31) mvy=31;
 
+           if(mvx == 0 && mvy == 0 && picture == 0) {
+               swf_SetBits(tag,1,1); // COD skip
+           } else {
+               int mode = 0;
+               int has_dc=0;
+               int y=0,c=0;
+               block_t b;
+               block_t b2;
+               
                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;
+
+               if(mvx==0 && mvy==0 && picture) { // only picture
+                   mode = 3;
+                   has_dc = 1;
+               }
+
+               if(picture) {
+                   RGBA* picblock = (RGBA*)picture;
+                   rgb2yuv(pic, picblock,16,16,16,16);
+                   /* TODO: if has_dc!=1, subtract 128 from rgb values */
+                   getregion(&b, pic, 0,0,16);
+                   dodctandquant(&b, &b2, 1, s->quant);
+                   getblockpatterns(&b2, &y, &c, 1);
+               } else {
+                   y=0;c=0;
+               }
+
+               codehuffman(tag, mcbpc_inter, mode*4+c);
+               codehuffman(tag, cbpy, mode==3?y:y^15);
+               
+               if(mode < 3) {
+                   /* has motion 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;
+               }
+
+               if(has_dc||y||c) {
+                   encode8x8(tag, b2.y1, has_dc, y&8);
+                   encode8x8(tag, b2.y2, has_dc, y&4);
+                   encode8x8(tag, b2.y3, has_dc, y&2);
+                   encode8x8(tag, b2.y4, has_dc, y&1);
+                   encode8x8(tag, b2.u, has_dc, c&2);
+                   encode8x8(tag, b2.v, has_dc, c&1);
+               }
            }
        }
     }
+    s->frame++;
 }
 
 #define TESTS
@@ -1313,7 +1393,7 @@ void test_copy_diff()
     VIDEOSTREAM stream;
     VIDEOSTREAM* s = &stream;
     TAG*tag;
-    RGBA*pic = malloc(256*256*sizeof(RGBA));
+    RGBA*pic = (RGBA*)rfx_alloc(256*256*sizeof(RGBA));
     block_t fb;
     int x,y;
     int bx,by;
@@ -1352,6 +1432,80 @@ void test_copy_diff()
 
 #ifdef MAIN
 #include "png.h"
+
+int compileSWFActionCode(const char *script, int version, void**data, int*len) {return 0;}
+
+void mkblack()
+{
+    SWF swf;
+    SWFPLACEOBJECT obj;
+    int frames = 88;
+    int width = 160;
+    int height = 112;
+    int x,y;
+    TAG*tag = 0;
+    RGBA rgb;
+    RGBA* pic = 0;
+    VIDEOSTREAM stream;
+   
+    pic = rfx_calloc(width*height*4);
+
+    memset(&swf,0,sizeof(SWF));
+    memset(&obj,0,sizeof(obj));
+
+    swf.fileVersion    = 6;
+    swf.frameRate      = 15*256;
+    swf.movieSize.xmax = 20*width;
+    swf.movieSize.ymax = 20*height;
+
+    swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
+    tag = swf.firstTag;
+    rgb.r = 0x00;rgb.g = 0x30;rgb.b = 0xff;
+    swf_SetRGB(tag,&rgb);
+
+    tag = swf_InsertTag(tag, ST_DEFINEVIDEOSTREAM);
+    swf_SetU16(tag, 1);
+    swf_SetVideoStreamDefine(tag, &stream, frames, width, height);
+    stream.do_motion = 0;
+
+    for(y=0;y<height;y++)  {
+       for(x=0;x<width;x++) {
+           int dx = x/16;
+           int dy = y/16;
+
+           pic[y*width+x].r = 0;
+           pic[y*width+x].g = 0;
+           pic[y*width+x].b = 0;
+           pic[y*width+x].a = 0;
+       }
+    }
+    tag = swf_InsertTag(tag, ST_VIDEOFRAME);
+    swf_SetU16(tag, 1);
+    
+    swf_SetVideoStreamIFrame(tag, &stream, pic, 7);
+
+    tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+    swf_GetPlaceObject(0, &obj);
+    
+    obj.depth = 4;
+    obj.id = 1;
+    
+    swf_SetPlaceObject(tag,&obj);
+
+    tag = swf_InsertTag(tag, ST_SHOWFRAME);
+    
+    swf_VideoStreamClear(&stream);
+
+    tag = swf_InsertTag(tag, ST_END);
+
+    int fi = open("black.swf", O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if(swf_WriteSWF(fi,&swf)<0) {
+       fprintf(stderr,"WriteSWF() failed.\n");
+    }
+    close(fi);
+    swf_FreeTags(&swf);
+}
+
 int main(int argn, char*argv[])
 {
     int fi;
@@ -1360,12 +1514,13 @@ int main(int argn, char*argv[])
     TAG * tag;
     RGBA* pic, *pic2, rgb;
     SWFPLACEOBJECT obj;
-    int width = 0;
-    int height = 0;
+    unsigned width = 0;
+    unsigned height = 0;
     int frames = 10;
     int framerate = 29;
     unsigned char*data;
-    char* fname = "/home/kramm/pics/peppers.png";
+    char* fname = "/home/kramm/pics/peppers_fromjpg.png";
+    //char* fname = "/home/kramm/pics/baboon.png";
     VIDEOSTREAM stream;
     double d = 1.0;
 
@@ -1373,13 +1528,15 @@ int main(int argn, char*argv[])
     test_copy_diff();
 #endif
 
+    mkblack();
+
     memset(&stream, 0, sizeof(stream));
 
-    getPNG(fname, &width, &height, &data);
-    pic = (RGBA*)malloc(width*height*sizeof(RGBA));
-    pic2 = (RGBA*)malloc(width*height*sizeof(RGBA));
+    png_load(fname, &width, &height, &data);
+    pic = (RGBA*)rfx_alloc(width*height*sizeof(RGBA));
+    pic2 = (RGBA*)rfx_alloc(width*height*sizeof(RGBA));
     memcpy(pic, data, width*height*sizeof(RGBA));
-    free(data);
+    rfx_free(data);
 
     printf("Compressing %s, size %dx%d\n", fname, width, height);
 
@@ -1389,11 +1546,11 @@ int main(int argn, char*argv[])
     swf.fileVersion    = 6;
     swf.frameRate      = framerate*256;
     swf.movieSize.xmax = 20*width*2;
-    swf.movieSize.ymax = 20*height-20*64;
+    swf.movieSize.ymax = 20*height;
 
     swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
     tag = swf.firstTag;
-    rgb.r = 0x00;rgb.g = 0x00;rgb.b = 0x00;
+    rgb.r = 0x00;rgb.g = 0x30;rgb.b = 0xff;
     swf_SetRGB(tag,&rgb);
 
     tag = swf_InsertTag(tag, ST_DEFINEVIDEOSTREAM);
@@ -1401,6 +1558,8 @@ int main(int argn, char*argv[])
     swf_SetVideoStreamDefine(tag, &stream, frames, width, height);
     stream.do_motion = 0;
 
+    //srand48(time(0));
+
     for(t=0;t<frames;t++)
     {
        int x,y;
@@ -1408,17 +1567,51 @@ int main(int argn, char*argv[])
        for(y=0,yy=0;y<height;y++,yy+=d)  {
            RGBA*line = &pic[((int)yy)*width];
            for(x=0,xx=0;x<width;x++,xx+=d) {
-               pic2[y*width+x] = line[((int)xx)];
+               int dx = x/16;
+               int dy = y/16;
+               if(dx==0 && dy==0) {
+                   pic2[y*width+x] = line[((int)xx)];
+                   pic2[y*width+x].r+=2;
+                   pic2[y*width+x].g+=2;
+                   pic2[y*width+x].b+=2;
+               } else {
+                   //pic2[y*width+x] = line[((int)xx)];
+                   //pic2[y*width+x].r = lrand48();//line[((int)xx)];
+                   //pic2[y*width+x].g = lrand48();//line[((int)xx)];
+                   //pic2[y*width+x].b = lrand48();//line[((int)xx)];
+                   pic2[y*width+x].r = 0;
+                   pic2[y*width+x].g = 0;
+                   pic2[y*width+x].b = 0;
+               }
+               /*if(dx==16 && dy==16) 
+                   pic2[y*width+x] = pic[(y-16*16)*width+(x-16*16)];*/
+               /*if(dx<=0 && dy<=0) {
+                   pic2[y*width+x] = line[((int)xx)];*/
+               /*if(x==0 && y==0) {
+                   RGBA color;
+                   memset(&color, 0, sizeof(RGBA));
+                   pic2[y*width+x] = color;*/
+               /*} else  {
+                   RGBA color;
+                   color.r = lrand48();
+                   color.g = lrand48();
+                   color.b = lrand48();
+                   color.a = 0;
+                   pic2[y*width+x] = color;
+               }*/
            }
        }
        printf("frame:%d\n", t);fflush(stdout);
 
+       if(t==1)
+           break;
+
        tag = swf_InsertTag(tag, ST_VIDEOFRAME);
        swf_SetU16(tag, 33);
        if(t==0)
-           swf_SetVideoStreamIFrame(tag, &stream, pic2, 9);
+           swf_SetVideoStreamIFrame(tag, &stream, pic2, 7);
        else {
-           swf_SetVideoStreamPFrame(tag, &stream, pic2, 9);
+           swf_SetVideoStreamPFrame(tag, &stream, pic2, 7);
        }
 
        tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
@@ -1441,7 +1634,7 @@ int main(int argn, char*argv[])
     tag = swf_InsertTag(tag, ST_END);
 
     fi = open("video3.swf", O_WRONLY|O_CREAT|O_TRUNC, 0644);
-    if(swf_WriteSWC(fi,&swf)<0) {
+    if(swf_WriteSWF(fi,&swf)<0) {
        fprintf(stderr,"WriteSWF() failed.\n");
     }
     close(fi);