4 Part of the swftools package.
6 Copyright (c) 2003 Matthias Kramm <kramm@quiss.org> */
12 #include "../rfxswf.h"
13 #include "h263tables.c"
16 void swf_SetVideoStreamDefine(TAG*tag, VIDEOSTREAM*stream, U16 frames, U16 width, U16 height)
18 width=width&~15; height=height&~15;
19 swf_SetU16(tag, frames);
20 swf_SetU16(tag, width);
21 swf_SetU16(tag, height);
22 swf_SetU8(tag, 1); /* smoothing on */
23 swf_SetU8(tag, 2); /* codec = h.263 sorenson spark */
25 memset(stream, 0, sizeof(VIDEOSTREAM));
26 stream->olinex = width;
28 height+=15;height&=~15;
29 stream->linex = width;
30 stream->width = width;
31 stream->height = height;
32 stream->current = (YUV*)malloc(width*height*sizeof(YUV));
33 stream->oldpic = (YUV*)malloc(width*height*sizeof(YUV));
35 memset(stream->oldpic, 0, width*height*sizeof(YUV));
36 memset(stream->current, 0, width*height*sizeof(YUV));
38 void swf_VideoStreamClear(VIDEOSTREAM*stream)
40 free(stream->oldpic);stream->oldpic = 0;
41 free(stream->current);stream->current = 0;
44 typedef struct _block_t
54 typedef struct _fblock_t
64 static int zigzagtable[64] = {
65 0, 1, 5, 6, 14, 15, 27, 28,
66 2, 4, 7, 13, 16, 26, 29, 42,
67 3, 8, 12, 17, 25, 30, 41, 43,
68 9, 11, 18, 24, 31, 40, 44, 53,
69 10, 19, 23, 32, 39, 45, 52, 54,
70 20, 22, 33, 38, 46, 51, 55, 60,
71 21, 34, 37, 47, 50, 56, 59, 61,
72 35, 36, 48, 49, 57, 58, 62, 63};
74 static void fzigzag(double*src)
79 ((int*)&tmp[zigzagtable[t]])[0] = ((int*)&src[t])[0];
80 ((int*)&tmp[zigzagtable[t]])[1] = ((int*)&src[t])[1];
82 memcpy(src, tmp, sizeof(double)*64);
85 #define PI 3.14159265358979
86 #define SQRT2 1.414214
87 #define RSQRT2 (1.0/1.414214)
89 static double table[8][8] =
91 {0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548},
92 {0.980785280403230,0.831469612302545,0.555570233019602,0.195090322016128,-0.195090322016128,-0.555570233019602,-0.831469612302545,-0.980785280403230},
93 {0.923879532511287,0.382683432365090,-0.382683432365090,-0.923879532511287,-0.923879532511287,-0.382683432365090,0.382683432365090,0.923879532511287},
94 {0.831469612302545,-0.195090322016128,-0.980785280403230,-0.555570233019602,0.555570233019602,0.980785280403230,0.195090322016129,-0.831469612302545},
95 {0.707106781186548,-0.707106781186547,-0.707106781186548,0.707106781186547,0.707106781186548,-0.707106781186547,-0.707106781186547,0.707106781186547},
96 {0.555570233019602,-0.980785280403230,0.195090322016128,0.831469612302545,-0.831469612302545,-0.195090322016128,0.980785280403231,-0.555570233019602},
97 {0.382683432365090,-0.923879532511287,0.923879532511287,-0.382683432365090,-0.382683432365091,0.923879532511287,-0.923879532511286,0.382683432365090},
98 {0.195090322016128,-0.555570233019602,0.831469612302545,-0.980785280403231,0.980785280403230,-0.831469612302545,0.555570233019602,-0.195090322016129}
101 static void dct(double*src)
112 c+=table[u][x]*src[v*8+x];
122 c+=table[v][y]*tmp[y*8+u];
128 static void idct(double*src)
138 c+=table[u][x]*src[y*8+u];
148 c+=table[v][y]*tmp[v*8+x];
154 static inline int truncate256(int a)
156 if(a>255) return 255;
161 static void getregion(fblock_t* bb, YUV*pic, int bx, int by, int linex)
163 YUV*p1 = &pic[by*linex*16+bx*16];
165 int y1=0, y2=0, y3=0, y4=0;
170 bb->u[u++] = (p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4;
171 bb->v[v++] = (p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4;
172 bb->y1[y1++] = p1[x].y;
173 bb->y2[y2++] = p1[x+8].y;
174 bb->y3[y3++] = p1[linex*8+x].y;
175 bb->y4[y4++] = p1[linex*8+x+8].y;
181 static void rgb2yuv(YUV*dest, RGBA*src, int dlinex, int slinex, int width, int height)
184 for(y=0;y<height;y++) {
185 for(x=0;x<width;x++) {
187 r = src[y*slinex+x].r;
188 g = src[y*slinex+x].g;
189 b = src[y*slinex+x].b;
190 /*dest[y*dlinex+x].y = (r*0.299 + g*0.587 + b*0.114);
191 dest[y*dlinex+x].u = (r*-0.169 + g*-0.332 + b*0.500 + 128.0);
192 dest[y*dlinex+x].v = (r*0.500 + g*-0.419 + b*-0.0813 + 128.0);*/
193 dest[y*dlinex+x].y = (r*((int)( 0.299*256)) + g*((int)( 0.587*256)) + b*((int)( 0.114 *256)))>>8;
194 dest[y*dlinex+x].u = (r*((int)(-0.169*256)) + g*((int)(-0.332*256)) + b*((int)( 0.500 *256))+ 128*256)>>8;
195 dest[y*dlinex+x].v = (r*((int)( 0.500*256)) + g*((int)(-0.419*256)) + b*((int)(-0.0813*256))+ 128*256)>>8;
199 static void copyregion(VIDEOSTREAM*s, YUV*dest, YUV*src, int bx, int by)
201 YUV*p1 = &src[by*s->linex*16+bx*16];
202 YUV*p2 = &dest[by*s->linex*16+bx*16];
205 memcpy(p1, p2, 16*sizeof(YUV));
206 p1+=s->linex;p2+=s->linex;
210 static void yuv2rgb(RGBA*dest, YUV*src, int linex, int width, int height)
213 for(y=0;y<height;y++) {
214 for(x=0;x<width;x++) {
216 u = src[y*linex+x].u;
217 v = src[y*linex+x].v;
218 yy = src[y*linex+x].y;
219 dest[y*linex+x].r = truncate256(yy + ((360*(v-128))>>8));
220 dest[y*linex+x].g = truncate256(yy - ((88*(u-128)+183*(v-128))>>8));
221 dest[y*linex+x].b = truncate256(yy + ((455 * (u-128))>>8));
225 static void copyblock(VIDEOSTREAM*s, YUV*dest, block_t*b, int bx, int by)
227 YUV*p1 = &dest[(by*16)*s->linex+bx*16];
228 YUV*p2 = &dest[(by*16+8)*s->linex+bx*16];
233 p1[x+0].u = b->u[(y/2)*8+(x/2)];
234 p1[x+0].v = b->v[(y/2)*8+(x/2)];
235 p1[x+0].y = b->y1[y*8+x];
236 p1[x+8].u = b->u[(y/2)*8+(x/2)+4];
237 p1[x+8].v = b->v[(y/2)*8+(x/2)+4];
238 p1[x+8].y = b->y2[y*8+x];
239 p2[x+0].u = b->u[(y/2+4)*8+(x/2)];
240 p2[x+0].v = b->v[(y/2+4)*8+(x/2)];
241 p2[x+0].y = b->y3[y*8+x];
242 p2[x+8].u = b->u[(y/2+4)*8+(x/2)+4];
243 p2[x+8].v = b->v[(y/2+4)*8+(x/2)+4];
244 p2[x+8].y = b->y4[y*8+x];
251 static int compareregions(VIDEOSTREAM*s, int bx, int by)
253 int linex = s->width;
254 YUV*p1 = &s->current[by*linex*16+bx*16];
255 YUV*p2 = &s->oldpic[by*linex*16+bx*16];
265 diff += y*y+(u*u+v*v)/4;
273 static inline int valtodc(int val)
281 /* TODO: what to do for zero values? skip the block? */
290 static int dctoval(int dc)
303 static int codehuffman(TAG*tag, struct huffcode*table, int index)
305 /* TODO: !optimize! */
307 while(table[index].code[i]) {
308 if(table[index].code[i]=='0')
309 swf_SetBits(tag, 0, 1);
311 swf_SetBits(tag, 1, 1);
317 static void quantize8x8(double*src, int*dest, int has_dc, int quant)
320 double q = 1.0/(quant*2);
322 dest[0] = valtodc((int)src[0]); /*DC*/
327 //dest[t] = (int)src[t];
328 /* exact: if(quant&1){dest[t] = (dest[t]/quant - 1)/2;}else{dest[t] = ((dest[t]+1)/quant - 1)/2;} */
329 //if(quant&1){dest[t] = (dest[t]/quant - 1)/2;}else{dest[t] = ((dest[t]+1)/quant - 1)/2;}
330 //dest[t] = dest[t]/(quant*2);
331 dest[t] = (int)(src[t]*q);
332 /* TODO: warn if this happens- the video will be buggy */
333 if(dest[t]>127) dest[t]=127;
334 if(dest[t]<-127) dest[t]=-127;
338 static void dequantize8x8(int*b, int has_dc, int quant)
342 b[0] = dctoval(b[0]); //DC
345 for(t=pos;t<64;t++) {
354 b[t] = quant*(2*b[t]+1); //-7,8,24,40
356 b[t] = quant*(2*b[t]+1)-1; //-8,7,23,39
363 /* paragraph 6.2.2, "clipping of reconstruction levels": */
364 if(b[t]>2047) b[t]=2047;
365 if(b[t]<-2048) b[t]=-2048;
369 static int hascoef(int*b, int has_dc)
375 for(t=pos;t<64;t++) {
382 static int coefbits8x8(int*bb, int has_dc)
393 for(last=63;last>=pos;last--) {
400 int run=0, level=0, islast=0,t;
401 while(!bb[pos] && pos<last) {
408 if(level<0) level=-level;
410 for(t=0;t<RLE_ESCAPE;t++) {
411 if(rle_params[t].run == run &&
412 rle_params[t].level == level &&
413 rle_params[t].last == islast) {
414 bits += rle[t].len + 1;
419 bits += rle[RLE_ESCAPE].len + 1 + 6 + 8;
428 static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
435 swf_SetBits(tag, bb[0], 8);
441 /* determine last non-null coefficient */
442 for(last=63;last>=pos;last--) {
443 /* TODO: we could leave out small coefficients
444 after a certain point (32?) */
448 /* blocks without coefficients should not be included
449 in the cbpy/cbpc patterns: */
458 while(!bb[pos] && pos<last) {
470 for(t=0;t<RLE_ESCAPE;t++) {
471 /* TODO: lookup table */
472 if(rle_params[t].run == run &&
473 rle_params[t].level == level &&
474 rle_params[t].last == islast) {
475 codehuffman(tag, rle, t);
476 swf_SetBits(tag, sign, 1);
481 codehuffman(tag, rle, RLE_ESCAPE);
488 swf_SetBits(tag, islast, 1);
489 swf_SetBits(tag, run, 6);
490 swf_SetBits(tag, level, 8); //FIXME: fixme??
500 static void dodct(fblock_t*fb)
503 dct(fb->y1); dct(fb->y2); dct(fb->y3); dct(fb->y4);
504 dct(fb->u); dct(fb->v);
513 static void doidct(block_t*b)
518 fb.y1[t] = b->y1[zigzagtable[t]];
519 fb.y2[t] = b->y2[zigzagtable[t]];
520 fb.y3[t] = b->y3[zigzagtable[t]];
521 fb.y4[t] = b->y4[zigzagtable[t]];
522 fb.u[t] = b->u[zigzagtable[t]];
523 fb.v[t] = b->v[zigzagtable[t]];
525 idct(fb.y1); idct(fb.y2); idct(fb.y3); idct(fb.y4);
526 idct(fb.u); idct(fb.v);
536 static void truncateblock(block_t*b)
540 b->y1[t] = truncate256(b->y1[t]);
541 b->y2[t] = truncate256(b->y2[t]);
542 b->y3[t] = truncate256(b->y3[t]);
543 b->y4[t] = truncate256(b->y4[t]);
544 b->u[t] = truncate256(b->u[t]);
545 b->v[t] = truncate256(b->v[t]);
549 static void quantize(fblock_t*fb, block_t*b, int has_dc, int quant)
551 quantize8x8(fb->y1, b->y1, has_dc, quant);
552 quantize8x8(fb->y2, b->y2, has_dc, quant);
553 quantize8x8(fb->y3, b->y3, has_dc, quant);
554 quantize8x8(fb->y4, b->y4, has_dc, quant);
555 quantize8x8(fb->u, b->u, has_dc, quant);
556 quantize8x8(fb->v, b->v, has_dc, quant);
558 static void dequantize(block_t*b, int has_dc, int quant)
560 dequantize8x8(b->y1, has_dc, quant);
561 dequantize8x8(b->y2, has_dc, quant);
562 dequantize8x8(b->y3, has_dc, quant);
563 dequantize8x8(b->y4, has_dc, quant);
564 dequantize8x8(b->u, has_dc, quant);
565 dequantize8x8(b->v, has_dc, quant);
568 static void getblockpatterns(block_t*b, int*cbpybits,int*cbpcbits, int has_dc)
573 *cbpybits|=hascoef(b->y1, has_dc)*8;
574 *cbpybits|=hascoef(b->y2, has_dc)*4;
575 *cbpybits|=hascoef(b->y3, has_dc)*2;
576 *cbpybits|=hascoef(b->y4, has_dc)*1;
578 *cbpcbits|=hascoef(b->u, has_dc)*2;
579 *cbpcbits|=hascoef(b->v, has_dc)*1;
582 static void setQuant(TAG*tag, int dquant)
589 swf_SetBits(tag, 0x0, 2);
590 } else if(dquant == -2) {
591 swf_SetBits(tag, 0x1, 2);
592 } else if(dquant == +1) {
593 swf_SetBits(tag, 0x2, 2);
594 } else if(dquant == +2) {
595 swf_SetBits(tag, 0x3, 2);
597 assert(0*strlen("invalid dquant"));
601 static void change_quant(int quant, int*dquant)
607 static void encode_blockI(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant)
612 int cbpcbits = 0, cbpybits=0;
614 getregion(&fb, s->current, bx, by, s->width);
617 change_quant(*quant, &dquant);
619 quantize(&fb, &b, 1, *quant);
621 //decode_blockI(s, &b, bx, by);
623 getblockpatterns(&b, &cbpybits, &cbpcbits, 1);
626 codehuffman(tag, mcbpc_intra, 4+cbpcbits);
628 codehuffman(tag, mcbpc_intra, 0+cbpcbits);
631 codehuffman(tag, cbpy, cbpybits);
634 setQuant(tag, dquant);
638 encode8x8(tag, b.y1, 1, cbpybits&8);
639 encode8x8(tag, b.y2, 1, cbpybits&4);
640 encode8x8(tag, b.y3, 1, cbpybits&2);
641 encode8x8(tag, b.y4, 1, cbpybits&1);
644 encode8x8(tag, b.u, 1, cbpcbits&2);
645 encode8x8(tag, b.v, 1, cbpcbits&1);
648 dequantize(&b, 1, *quant);
651 copyblock(s, s->current, &b, bx, by);
654 static void yuvdiff(fblock_t*a, fblock_t*b)
658 a->y1[t] = (a->y1[t] - b->y1[t]);
659 a->y2[t] = (a->y2[t] - b->y2[t]);
660 a->y3[t] = (a->y3[t] - b->y3[t]);
661 a->y4[t] = (a->y4[t] - b->y4[t]);
662 a->u[t] = (a->u[t] - b->u[t]);
663 a->v[t] = (a->v[t] - b->v[t]);
667 static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant)
676 int cbpcbits = 0, cbpybits=0;
686 diff = compareregions(s, bx, by);
687 if(diff < 16 /*TODO: should be a parameter- good values are between 32 and 48 */) {
688 swf_SetBits(tag, 1,1); /* cod=1, block skipped */
689 copyregion(s, s->current, s->oldpic, bx, by);
693 getregion(&fb, s->current, bx, by, s->width);
695 { /* consider I-block */
698 memcpy(&fb_i, &fb, sizeof(fblock_t));
700 quantize(&fb_i, &b_i, 1, *quant);
701 getblockpatterns(&b_i, &y, &c, 1);
703 bits_i += mcbpc_inter[3*4+c].len;
704 bits_i += cbpy[y].len;
705 bits_i += coefbits8x8(b_i.y1, 1);
706 bits_i += coefbits8x8(b_i.y2, 1);
707 bits_i += coefbits8x8(b_i.y3, 1);
708 bits_i += coefbits8x8(b_i.y4, 1);
709 bits_i += coefbits8x8(b_i.u, 1);
710 bits_i += coefbits8x8(b_i.v, 1);
713 { /* consider mvd(0,0)-block */
716 memcpy(&fbdiff, &fb, sizeof(fblock_t));
717 getregion(&fbold_v00, s->oldpic, bx, by, s->linex);
718 yuvdiff(&fbdiff, &fbold_v00);
720 quantize(&fbdiff, &b_v00, 0, *quant);
721 getblockpatterns(&b_v00, &y, &c, 0);
723 bits_v00 += mcbpc_inter[0*4+c].len;
724 bits_v00 += cbpy[y^15].len;
725 bits_v00 += mvd[32].len; // (0,0)
726 bits_v00 += mvd[32].len;
727 bits_v00 += coefbits8x8(b_v00.y1, 0);
728 bits_v00 += coefbits8x8(b_v00.y2, 0);
729 bits_v00 += coefbits8x8(b_v00.y3, 0);
730 bits_v00 += coefbits8x8(b_v00.y4, 0);
731 bits_v00 += coefbits8x8(b_v00.u, 0);
732 bits_v00 += coefbits8x8(b_v00.v, 0);
735 if(bits_i > bits_v00)
737 /* mvd (0,0) block (mode=0) */
739 mode = 0; // mvd w/o mvd24
741 memcpy(&b, &b_v00, sizeof(block_t));
743 getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
744 swf_SetBits(tag,0,1); // COD
745 codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
746 codehuffman(tag, cbpy, cbpybits^15);
749 codehuffman(tag, mvd, 32);
750 codehuffman(tag, mvd, 32);
753 encode8x8(tag, b.y1, has_dc, cbpybits&8);
754 encode8x8(tag, b.y2, has_dc, cbpybits&4);
755 encode8x8(tag, b.y3, has_dc, cbpybits&2);
756 encode8x8(tag, b.y4, has_dc, cbpybits&1);
759 encode8x8(tag, b.u, has_dc, cbpcbits&2);
760 encode8x8(tag, b.v, has_dc, cbpcbits&1);
762 /* -- reconstruction -- */
763 dequantize(&b, 0, *quant);
766 b.y1[t] = truncate256(b.y1[t] + (int)fbold_v00.y1[t]);
767 b.y2[t] = truncate256(b.y2[t] + (int)fbold_v00.y2[t]);
768 b.y3[t] = truncate256(b.y3[t] + (int)fbold_v00.y3[t]);
769 b.y4[t] = truncate256(b.y4[t] + (int)fbold_v00.y4[t]);
770 b.u[t] = truncate256(b.u[t] + (int)fbold_v00.u[t]);
771 b.v[t] = truncate256(b.v[t] + (int)fbold_v00.v[t]);
773 copyblock(s, s->current, &b, bx, by);
776 /* i block (mode=3) */
779 memcpy(&b, &b_i, sizeof(block_t));
781 //quantize(&fb, &b, has_dc, *quant);
782 getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
783 swf_SetBits(tag,0,1); // COD
784 codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
785 codehuffman(tag, cbpy, cbpybits);
788 encode8x8(tag, b.y1, has_dc, cbpybits&8);
789 encode8x8(tag, b.y2, has_dc, cbpybits&4);
790 encode8x8(tag, b.y3, has_dc, cbpybits&2);
791 encode8x8(tag, b.y4, has_dc, cbpybits&1);
794 encode8x8(tag, b.u, has_dc, cbpcbits&2);
795 encode8x8(tag, b.v, has_dc, cbpcbits&1);
797 /* -- reconstruction -- */
798 dequantize(&b, 1, *quant);
801 copyblock(s, s->current, &b, bx, by);
808 quantize(&fb, &b, has_dc, *quant);
809 getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
811 if(!dquant && has_mvd && !has_mvd24 && !has_dc) mode = 0;
812 else if(dquant && has_mvd && !has_mvd24 && !has_dc) mode = 1;
813 else if(!dquant && has_mvd && has_mvd24 && !has_dc) mode = 2;
814 else if(!dquant && !has_mvd && !has_mvd24 && has_dc) mode = 3;
815 else if(dquant && !has_mvd && !has_mvd24 && has_dc) mode = 4;
818 swf_SetBits(tag,0,1); /* cod - 1 if we're not going to code this block*/
820 codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
821 codehuffman(tag, cbpy, (mode==3 || mode==4)?cbpybits:cbpybits^15);
824 setQuant(tag, dquant);
829 codehuffman(tag, mvd, 32);
830 codehuffman(tag, mvd, 32);
836 encode8x8(tag, b.y1, has_dc, cbpybits&8);
837 encode8x8(tag, b.y2, has_dc, cbpybits&4);
838 encode8x8(tag, b.y3, has_dc, cbpybits&2);
839 encode8x8(tag, b.y4, has_dc, cbpybits&1);
842 encode8x8(tag, b.u, has_dc, cbpcbits&2);
843 encode8x8(tag, b.v, has_dc, cbpcbits&1);
847 #define TYPE_IFRAME 0
848 #define TYPE_PFRAME 1
850 static void writeHeader(TAG*tag, int width, int height, int frame, int quant, int type)
853 swf_SetU16(tag, frame);
854 swf_SetBits(tag, 1, 17); /* picture start code*/
855 swf_SetBits(tag, 0, 5); /* version=0, version 1 would optimize rle behaviour*/
856 swf_SetBits(tag, frame, 8); /* time reference */
858 /* write dimensions, taking advantage of some predefined sizes
859 if the opportunity presents itself */
860 i32 = width<<16|height;
863 case 352<<16|288: swf_SetBits(tag, 2, 3);break;
864 case 176<<16|144: swf_SetBits(tag, 3, 3);break;
865 case 128<<16|96: swf_SetBits(tag, 4, 3);break;
866 case 320<<16|240: swf_SetBits(tag, 5, 3);break;
867 case 160<<16|120: swf_SetBits(tag, 6, 3);break;
869 if(width>255 || height>255) {
870 swf_SetBits(tag, 1, 3);
871 swf_SetBits(tag, width, 16);
872 swf_SetBits(tag, height, 16);
874 swf_SetBits(tag, 0, 3);
875 swf_SetBits(tag, width, 8);
876 swf_SetBits(tag, height, 8);
880 swf_SetBits(tag, type, 2); /* I-Frame or P-Frame */
881 swf_SetBits(tag, 0, 1); /* No deblock filter */
883 swf_SetBits(tag, quant, 5); /* quantizer (1-31), may be updated later on*/
884 swf_SetBits(tag, 0, 1); /* No extra info */
887 void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
889 int bx, by, bbx, bby;
892 if(quant>31) quant=31;
894 writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_IFRAME);
896 bbx = (s->width+15)/16; //TODO: move bbx,bby into VIDEOSTREAM
897 bby = (s->height+15)/16;
899 rgb2yuv(s->current, pic, s->linex, s->olinex, s->width, s->height);
901 for(by=0;by<bby;by++)
903 for(bx=0;bx<bbx;bx++)
905 encode_blockI(tag, s, bx, by, &quant);
909 memcpy(s->oldpic, s->current, s->width*s->height*sizeof(YUV));
912 void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
914 int bx, by, bbx, bby;
917 if(quant>31) quant=31;
919 writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_PFRAME);
921 bbx = (s->width+15)/16;
922 bby = (s->height+15)/16;
924 rgb2yuv(s->current, pic, s->linex, s->olinex, s->width, s->height);
926 for(by=0;by<bby;by++)
928 for(bx=0;bx<bbx;bx++)
930 encode_blockP(tag, s, bx, by, &quant);
934 memcpy(s->oldpic, s->current, s->width*s->height*sizeof(YUV));
938 FILE*fi = fopen("test.ppm", "wb");
939 yuv2rgb(pic, s->current, s->linex, s->width, s->height);
940 fprintf(fi, "P6\n%d %d\n255\n", s->width, s->height);
941 for(t=0;t<s->width*s->height;t++)
943 fwrite(&pic[t].r, 1, 1, fi);
944 fwrite(&pic[t].g, 1, 1, fi);
945 fwrite(&pic[t].b, 1, 1, fi);
953 int main(int argn, char*argv[])
959 RGBA* pic, *pic2, rgb;
966 char* fname = "/home/kramm/pics/lena.png";
970 memset(&stream, 0, sizeof(stream));
972 getPNG(fname, &width, &height, &data);
973 pic = (RGBA*)malloc(width*height*sizeof(RGBA));
974 pic2 = (RGBA*)malloc(width*height*sizeof(RGBA));
975 memcpy(pic, data, width*height*sizeof(RGBA));
978 printf("Compressing %s, size %dx%d\n", fname, width, height);
980 memset(&swf,0,sizeof(SWF));
981 memset(&obj,0,sizeof(obj));
984 swf.frameRate = framerate*256;
985 swf.movieSize.xmax = 20*width;
986 swf.movieSize.ymax = 20*height;
988 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
990 rgb.r = 0x00;rgb.g = 0x00;rgb.b = 0x00;
991 swf_SetRGB(tag,&rgb);
993 tag = swf_InsertTag(tag, ST_DEFINEVIDEOSTREAM);
995 swf_SetVideoStreamDefine(tag, &stream, frames, width, height);
997 for(t=0;t<frames;t++)
1001 for(y=0,yy=0;y<height;y++,yy+=d) {
1002 RGBA*line = &pic[((int)yy)*width];
1003 for(x=0,xx=0;x<width;x++,xx+=d) {
1004 pic2[y*width+x] = line[((int)xx)];
1007 printf("frame:%d\n", t);fflush(stdout);
1009 tag = swf_InsertTag(tag, ST_VIDEOFRAME);
1010 swf_SetU16(tag, 33);
1012 swf_SetVideoStreamIFrame(tag, &stream, pic2, 9);
1014 swf_SetVideoStreamPFrame(tag, &stream, pic2, 9);
1016 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1017 swf_GetPlaceObject(0, &obj);
1026 swf_SetPlaceObject(tag,&obj);
1028 tag = swf_InsertTag(tag, ST_SHOWFRAME);
1032 swf_VideoStreamClear(&stream);
1034 tag = swf_InsertTag(tag, ST_END);
1036 fi = open("video3.swf", O_WRONLY|O_CREAT|O_TRUNC, 0644);
1037 if(swf_WriteSWC(fi,&swf)<0) {
1038 fprintf(stderr,"WriteSWF() failed.\n");