4 Part of the swftools package.
6 Copyright (c) 2003 Matthias Kramm <kramm@quiss.org> */
12 #include "../lib/rfxswf.h"
14 #include "h263tables.c"
17 void swf_SetVideoStreamDefine(TAG*tag, U16 frames, U16 width, U16 height)
19 width=width&~15; height=height&~15;
20 swf_SetU16(tag, frames);
21 swf_SetU16(tag, width);
22 swf_SetU16(tag, height);
23 swf_SetU8(tag, 1); /* smoothing on */
24 swf_SetU8(tag, 2); /* codec = h.263 sorenson spark */
50 0, 1, 5, 6, 14, 15, 27, 28,
51 2, 4, 7, 13, 16, 26, 29, 42,
52 3, 8, 12, 17, 25, 30, 41, 43,
53 9, 11, 18, 24, 31, 40, 44, 53,
54 10, 19, 23, 32, 39, 45, 52, 54,
55 20, 22, 33, 38, 46, 51, 55, 60,
56 21, 34, 37, 47, 50, 56, 59, 61,
57 35, 36, 48, 49, 57, 58, 62, 63};
61 tmp[table[t]] = src[t];
63 memcpy(src, tmp, sizeof(int)*64);
66 #define PI 3.14159265358979
67 #define SQRT2 1.414214
68 #define RSQRT2 (1.0/1.414214)
81 double f = 0.25*cos(PI*(2.0*x+1.0)*u/16.0)*cos(PI*(2.0*y+1.0)*v/16.0);
88 memcpy(src, tmp, sizeof(double)*64);
102 double f = 0.25*cos(PI*(2.0*x+1.0)*u/16.0)*cos(PI*(2.0*y+1.0)*v/16.0);
109 memcpy(src, tmp, sizeof(double)*64);
112 void getregion(struct fblock_t* bb, RGBA*pic, int bx, int by, int width, int height)
114 RGBA*p1 = &pic[by*width*16+bx*16];
117 int y1=0, y2=0, y3=0, y4=0;
123 r = (p2[x*2].r + p2[x*2+1].r + p2[linex+x*2].r + p2[linex+x*2+1].r)/4.0;
124 g = (p2[x*2].g + p2[x*2+1].g + p2[linex+x*2].g + p2[linex+x*2+1].g)/4.0;
125 b = (p2[x*2].b + p2[x*2+1].b + p2[linex+x*2].b + p2[linex+x*2+1].b)/4.0;
126 bb->u[u++] = (r*-0.169 + g*-0.332 + b*0.500 + 128.0);
127 bb->v[v++] = (r*0.500 + g*-0.419 + b*-0.0813 + 128.0);
129 r = p1[x].r; g = p1[x].g; b = p1[x].b;
130 bb->y1[y1++] = (r*0.299 + g*0.587 + b*0.114);
131 r = p1[x+8].r; g = p1[x+8].g; b = p1[x+8].b;
132 bb->y2[y2++] = (r*0.299 + g*0.587 + b*0.114);
133 r = p1[linex*8+x].r; g = p1[linex*8+x].g; b = p1[linex*8+x].b;
134 bb->y3[y3++] = (r*0.299 + g*0.587 + b*0.114);
135 r = p1[linex*8+x+8].r; g = p1[linex*8+x+8].g; b = p1[linex*8+x+8].b;
136 bb->y4[y4++] = (r*0.299 + g*0.587 + b*0.114);
149 /* TODO: what to do for zero values? skip the block? */
159 void codehuffman(TAG*tag, struct huffcode*table, int index)
161 /* TODO: !optimize! */
163 while(table[index].code[i]) {
164 if(table[index].code[i]=='0')
165 swf_SetBits(tag, 0, 1);
167 swf_SetBits(tag, 1, 1);
174 void quantize(double*src, int*dest, int quant, int has_dc)
178 dest[0] = (int)src[0]; /*DC*/
179 dest[0] = valtodc(dest[0]);
184 dest[t] = (int)src[t];
185 //val = (quant*(2*level+1)-1)+quant&1
187 dest[t] = (dest[t]/quant - 1)/2;
189 dest[t] = ((dest[t]+1)/quant - 1)/2;
194 int hascoef(int*b, int has_dc)
201 for(t=pos;t<64;t++) {
202 if(b[t]<=-range || b[t]>=range)
208 void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
214 swf_SetBits(tag, bb[0], 8);
220 /* determine last non-null coefficient */
221 for(last=63;last>=pos;last--) {
226 /* blocks without coefficients should not be included
227 in the cbpy/cbpc patterns */
234 while(!bb[pos] && pos<last) {
245 for(t=0;t<RLE_ESCAPE;t++) {
246 if(rle_params[t].run == run &&
247 rle_params[t].level == level &&
248 rle_params[t].last == islast) {
249 codehuffman(tag, rle, t);
250 swf_SetBits(tag, sign, 1);
255 codehuffman(tag, rle, RLE_ESCAPE);
258 if(level<-127) level = -127;
259 if(level>127) level = 127;
261 swf_SetBits(tag, islast, 1);
262 swf_SetBits(tag, run, 6);
263 swf_SetBits(tag, level, 8); //fixme
271 //codehuffman(tag, rle, 58);
272 //swf_SetBits(tag, 1, 1); //sign
277 void encode_blockI(TAG*tag, RGBA*pic, int bx, int by, int width, int height, int*quant)
280 int dquant=0; /* TODO: should we take advantage of the dquant feature?*/
285 int y1[64],y2[64],y3[64],y4[64],u[64],v[64];
287 getregion(&b, pic, bx, by, width, height);
288 dct(b.y1); quantize(b.y1,y1,1,*quant); zigzag(y1); cbpybits|=hascoef(y1, 1)*8;
289 dct(b.y2); quantize(b.y2,y2,1,*quant); zigzag(y2); cbpybits|=hascoef(y2, 1)*4;
290 dct(b.y3); quantize(b.y3,y3,1,*quant); zigzag(y3); cbpybits|=hascoef(y3, 1)*2;
291 dct(b.y4); quantize(b.y4,y4,1,*quant); zigzag(y4); cbpybits|=hascoef(y4, 1)*1;
292 dct(b.u); quantize(b.u,u,1,*quant); zigzag(u); cbpcbits|=hascoef(u, 1)*2;
293 dct(b.v); quantize(b.v,v,1,*quant); zigzag(v); cbpcbits|=hascoef(v, 1)*1;
296 codehuffman(tag, mcbpc_intra, 4+cbpcbits);
298 codehuffman(tag, mcbpc_intra, 0+cbpcbits);
300 //swf_SetBits(tag, 1, 1); /*cbpc-00 mb_type=3 (no bquant), cbc=0*/
302 /* if this was an intra frame, we'd need to code (cbpybits^15) */
303 codehuffman(tag, cbpy, cbpybits);
309 swf_SetBits(tag, 0x3, 2);
313 encode8x8(tag, y1, 1, cbpybits&8);
314 encode8x8(tag, y2, 1, cbpybits&4);
315 encode8x8(tag, y3, 1, cbpybits&2);
316 encode8x8(tag, y4, 1, cbpybits&1);
317 /*swf_SetBits(tag, 0x1, 8);
318 swf_SetBits(tag, 0xfe, 8);
319 swf_SetBits(tag, 0x1, 8);
320 swf_SetBits(tag, 0x1, 8);*/
323 encode8x8(tag, u, 1, cbpcbits&2);
324 encode8x8(tag, v, 1, cbpcbits&1);
325 /*swf_SetBits(tag, 0xfe, 8);
326 swf_SetBits(tag, 0xfe, 8);*/
329 void swf_SetVideoStreamIFrame(TAG*tag, RGBA*pic, U16 width, U16 height, int frame)
332 int bx, by, bbx, bby;
335 width=width&~15; height=height&~15;
337 swf_SetU16(tag, frame);
338 swf_SetBits(tag, 1, 17); /* picture start code*/
339 swf_SetBits(tag, 0, 5); /* version=0, version 1 would optimize rle behaviour*/
340 swf_SetBits(tag, frame, 8); /* time reference */
342 /* write dimensions, taking advantage of some predefined sizes
343 if the opportunity presents itself */
344 i32 = width<<16|height;
347 case 352<<16|288: swf_SetBits(tag, 2, 3);break;
348 case 176<<16|144: swf_SetBits(tag, 3, 3);break;
349 case 128<<16|96: swf_SetBits(tag, 4, 3);break;
350 case 320<<16|240: swf_SetBits(tag, 5, 3);break;
351 case 160<<16|120: swf_SetBits(tag, 6, 3);break;
353 if(width>255 || height>255) {
354 swf_SetBits(tag, 1, 3);
355 swf_SetBits(tag, width, 16);
356 swf_SetBits(tag, height, 16);
358 swf_SetBits(tag, 0, 3);
359 swf_SetBits(tag, width, 8);
360 swf_SetBits(tag, height, 8);
364 swf_SetBits(tag, 0, 2); /* I-Frame */
365 swf_SetBits(tag, 0, 1); /* No deblock filter */
366 swf_SetBits(tag, quant, 5); /* quantizer (1-31), may be updated later on*/
367 swf_SetBits(tag, 0, 1); /* No extra info */
370 bby = (height+15)/16;
372 for(by=0;by<bby;by++)
374 for(bx=0;bx<bbx;bx++)
376 encode_blockI(tag, pic, bx, by, width, height, &quant);
393 char* fname = "/home/kramm/pics/lena.png";
395 getimage(fname, &width, &height, &data);
396 pic = (RGBA*)malloc(width*height*sizeof(RGBA));
397 memcpy(pic, data, width*height*sizeof(RGBA));
399 printf("Compressing %s, size %dx%d\n", fname, width, height);
401 memset(&swf,0,sizeof(SWF));
402 memset(&obj,0,sizeof(obj));
405 swf.frameRate = 29*256;
406 swf.movieSize.xmax = 20*width;
407 swf.movieSize.ymax = 20*height;
409 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
411 rgb.r = 0x00;rgb.g = 0x00;rgb.b = 0x00;
412 swf_SetRGB(tag,&rgb);
414 tag = swf_InsertTag(tag, ST_DEFINEVIDEOSTREAM);
416 swf_SetVideoStreamDefine(tag, frames, width, height);
418 for(t=0;t<frames;t++)
420 tag = swf_InsertTag(tag, ST_VIDEOFRAME);
422 swf_SetVideoStreamIFrame(tag, pic, width, height, t);
424 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
425 swf_GetPlaceObject(0, &obj);
434 swf_SetPlaceObject(tag,&obj);
436 tag = swf_InsertTag(tag, ST_SHOWFRAME);
439 tag = swf_InsertTag(tag, ST_END);
441 fi = open("video3.swf", O_WRONLY|O_CREAT|O_TRUNC, 0644);
442 if(swf_WriteSWF(fi,&swf)<0) {
443 fprintf(stderr,"WriteSWF() failed.\n");