#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
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
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;
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);
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)
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;
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)
{
#endif
}
-static int uline[64],vline[64],yline[64];
-void swf_SetVideoStreamMover(TAG*tag, VIDEOSTREAM*s, 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);
{
for(bx=0;bx<s->bbx;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=0;//(lrand48()%4)-2;
- int mvy=3;
+ 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;
- 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 == 0) {
+ swf_SetBits(tag,1,1); // COD skip
} else {
- /* i block (mode=3) */
- int mode = 3;
- int has_dc = 1;
- int cbpybits,cbpcbits;
- int t;
+ int mode = 0;
+ int has_dc=0;
+ int y=0,c=0;
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);
+ block_t b2;
+
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);
+
+ 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
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;
#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;
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;
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));
+ 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);
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);
swf_SetVideoStreamDefine(tag, &stream, frames, width, height);
stream.do_motion = 0;
+ //srand48(time(0));
+
for(t=0;t<frames;t++)
{
int x,y;
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);
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);