moved from mkvideo.c
[swftools.git] / lib / h.263 / mkvideo.c
1 /* mkvideo.c
2    Create a video file.
3
4    Part of the swftools package.
5
6    Copyright (c) 2003 Matthias Kramm <kramm@quiss.org> */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <assert.h>
11 #include <math.h>
12 #include "../rfxswf.h"
13 #include "h263tables.c"
14 #include "swfvideo.h"
15
16 #ifdef MAIN
17 U16 totalframes = 0;
18 #endif
19 void swf_SetVideoStreamDefine(TAG*tag, VIDEOSTREAM*stream, U16 frames, U16 width, U16 height)
20 {
21     swf_SetU16(tag, frames);
22     swf_SetU16(tag, width);
23     swf_SetU16(tag, height);
24     //swf_SetU8(tag, 1); /* smoothing on */
25     swf_SetU8(tag, 0); /* smoothing off */
26     swf_SetU8(tag, 2); /* codec = h.263 sorenson spark */
27
28     totalframes = frames;
29
30     memset(stream, 0, sizeof(VIDEOSTREAM));
31     stream->olinex = width;
32     width+=15;width&=~15;
33     height+=15;height&=~15;
34     stream->linex = width;
35     stream->width = width;
36     stream->height = height;
37     stream->bbx = width/16;
38     stream->bby = height/16;
39     stream->current = (YUV*)malloc(width*height*sizeof(YUV));
40     stream->oldpic = (YUV*)malloc(width*height*sizeof(YUV));
41     stream->mvdx = (int*)malloc(stream->bbx*stream->bby*sizeof(int));
42     stream->mvdy = (int*)malloc(stream->bbx*stream->bby*sizeof(int));
43     stream->do_motion = 0;
44
45     memset(stream->oldpic, 0, width*height*sizeof(YUV));
46     memset(stream->current, 0, width*height*sizeof(YUV));
47 }
48 void swf_VideoStreamClear(VIDEOSTREAM*stream)
49 {
50     free(stream->oldpic);stream->oldpic = 0;
51     free(stream->current);stream->current = 0;
52     free(stream->mvdx);stream->mvdx=0;
53     free(stream->mvdy);stream->mvdy=0;
54 }
55
56 typedef struct _block_t
57 {
58     int y1[64];
59     int y2[64];
60     int y3[64];
61     int y4[64];
62     int u[64];
63     int v[64];
64 } block_t;
65
66 static int zigzagtable[64] = {
67     0, 1, 5, 6, 14, 15, 27, 28,
68     2, 4, 7, 13, 16, 26, 29, 42,
69     3, 8, 12, 17, 25, 30, 41, 43,
70     9, 11, 18, 24, 31, 40, 44, 53,
71     10, 19, 23, 32, 39, 45, 52, 54,
72     20, 22, 33, 38, 46, 51, 55, 60,
73     21, 34, 37, 47, 50, 56, 59, 61,
74     35, 36, 48, 49, 57, 58, 62, 63};
75
76 static void zigzag(int*src)
77 {
78     int tmp[64];
79     int t;
80     for(t=0;t<64;t++) {
81         tmp[zigzagtable[t]] = src[t];
82     }
83     memcpy(src, tmp, sizeof(int)*64);
84 }
85
86 #define PI 3.14159265358979
87 #define SQRT2 1.414214
88 #define RSQRT2 (1.0/1.414214)
89
90 static double table[8][8] =
91 {
92 {0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548,0.707106781186548},
93 {0.980785280403230,0.831469612302545,0.555570233019602,0.195090322016128,-0.195090322016128,-0.555570233019602,-0.831469612302545,-0.980785280403230},
94 {0.923879532511287,0.382683432365090,-0.382683432365090,-0.923879532511287,-0.923879532511287,-0.382683432365090,0.382683432365090,0.923879532511287},
95 {0.831469612302545,-0.195090322016128,-0.980785280403230,-0.555570233019602,0.555570233019602,0.980785280403230,0.195090322016129,-0.831469612302545},
96 {0.707106781186548,-0.707106781186547,-0.707106781186548,0.707106781186547,0.707106781186548,-0.707106781186547,-0.707106781186547,0.707106781186547},
97 {0.555570233019602,-0.980785280403230,0.195090322016128,0.831469612302545,-0.831469612302545,-0.195090322016128,0.980785280403231,-0.555570233019602},
98 {0.382683432365090,-0.923879532511287,0.923879532511287,-0.382683432365090,-0.382683432365091,0.923879532511287,-0.923879532511286,0.382683432365090},
99 {0.195090322016128,-0.555570233019602,0.831469612302545,-0.980785280403231,0.980785280403230,-0.831469612302545,0.555570233019602,-0.195090322016129}
100 };
101
102 static void dct(int*src)
103 {
104     double tmp[64];
105     int x,y,u,v,t;
106
107     for(v=0;v<8;v++)
108     for(u=0;u<8;u++)
109     {
110         double c = 0;
111         for(x=0;x<8;x++)
112         {
113             c+=table[u][x]*src[v*8+x];
114         }
115         tmp[v*8+u] = c;
116     }
117     for(u=0;u<8;u++)
118     for(v=0;v<8;v++)
119     {
120         double c = 0;
121         for(y=0;y<8;y++)
122         {
123             c+=table[v][y]*tmp[y*8+u];
124         }
125         src[v*8+u] = (int)(c*0.25+0.5);
126     }
127 }
128
129 static void idct(int*src)
130 {
131     double tmp[64];
132     int x,y,u,v;
133     for(y=0;y<8;y++)
134     for(x=0;x<8;x++)
135     {
136         double c = 0;
137         for(u=0;u<8;u++)
138         {
139             c+=table[u][x]*src[y*8+u];
140         }
141         tmp[y*8+x] = c;
142     }
143     for(y=0;y<8;y++)
144     for(x=0;x<8;x++)
145     {
146         double c = 0;
147         for(v=0;v<8;v++)
148         {
149             c+=table[v][y]*tmp[v*8+x];
150         }
151         src[y*8+x] = (int)(c*0.25+0.5);
152     }
153 }
154
155 static double c[8] = {1.0,
156 0.980785280403230, // cos(Pi*1/16), sin(Pi*7/16)
157 0.923879532511287, // cos(Pi*2/16), sin(Pi*6/16)
158 0.831469612302545, // cos(Pi*3/16), sin(Pi*5/16)
159 0.707106781186548, // cos(Pi*4/16), sin(Pi*4/16), 1/sqrt(2)
160 0.555570233019602, // cos(Pi*5/16), sin(Pi*3/16)
161 0.382683432365090, // cos(Pi*6/16), sin(Pi*2/16)
162 0.195090322016128 // cos(Pi*7/16), sin(Pi*1/16)
163 };
164
165 static double cc[8];
166 int ccquant = -1;
167
168 static void preparequant(int quant)
169 {
170     if(ccquant == quant)
171         return;
172     cc[0] = c[0]/(quant*2*4);
173     cc[1] = c[1]/(quant*2*4);
174     cc[2] = c[2]/(quant*2*4);
175     cc[3] = c[3]/(quant*2*4);
176     cc[4] = c[4]/(quant*2*4);
177     cc[5] = c[5]/(quant*2*4);
178     cc[6] = c[6]/(quant*2*4);
179     cc[7] = c[7]/(quant*2*4);
180     ccquant = quant;
181 }
182
183 inline static void innerdct(double*a,double*b, double*c)
184 {
185     // c1*c7*2 = c6
186     // c2*c6*2 = c4
187     // c3*c5*2 = c2
188     // c4*c4*2 = 1
189
190      //{  1,  3,  5,  7, -7, -5, -3, -1},
191      //{  3, -7, -1, -5,  5,  1,  7, -3},
192      //{  5, -1,  7,  3, -3, -7,  1, -5},
193      //{  7, -5,  3, -1,  1, -3,  5, -7}
194     double b0,b1,b2,b3,b4,b5;
195     b2 = (a[0]+a[7]);
196     b3 = (a[1]+a[6]);
197     b4 = (a[2]+a[5]);
198     b5 = (a[3]+a[4]);
199
200     b0 = (b2+b5)*c[4];
201     b1 = (b3+b4)*c[4];
202     b[0*8] = b0 + b1;
203     b[4*8] = b0 - b1;
204     b[2*8] = (b2-b5)*c[2] + (b3-b4)*c[6];
205     b[6*8] = (b2-b5)*c[6] + (b4-b3)*c[2];
206
207     b0 = (a[0]-a[7]);
208     b1 = (a[1]-a[6]);
209     b2 = (a[2]-a[5]);
210     b3 = (a[3]-a[4]);
211
212     b[1*8] = b0*c[1] + b1*c[3] + b2*c[5] + b3*c[7];
213     b[3*8] = b0*c[3] - b1*c[7] - b2*c[1] - b3*c[5];
214     b[5*8] = b0*c[5] - b1*c[1] + b2*c[7] + b3*c[3];
215     b[7*8] = b0*c[7] - b1*c[5] + b2*c[3] - b3*c[1];
216 }
217
218 static void dct2(int*src, int*dest)
219 {
220     double tmp[64], tmp2[64];
221     double*p;
222     int u,x,v,t;
223
224     for(t=0;t<64;t++)
225         tmp2[t] = src[t];
226
227     for(v=0;v<8;v++)
228     {
229         double* a=&tmp2[v*8];
230         double* b=&tmp[v];
231         innerdct(a,b,c);
232     }
233     for(v=0;v<8;v++)
234     {
235         double* a=&tmp[v*8];
236         double* b=&tmp2[v];
237         innerdct(a,b,cc);
238     }
239     for(t=0;t<64;t++) {
240         dest[zigzagtable[t]] = (int)(tmp2[t]);
241     }
242 }
243
244
245 static inline int truncate256(int a)
246 {
247     if(a>255) return 255;
248     if(a<0) return 0;
249     return a;
250 }
251
252 static void getregion(block_t* bb, YUV*pic, int posx, int posy, int linex)
253 {
254     YUV*p1;
255     YUV*p2;
256     int y1=0, y2=0, y3=0, y4=0;
257     int u=0,v=0;
258     int x,y;
259     posx*=16;
260     posy*=16;
261     p1 = &pic[posy*linex+posx];
262     p2 = p1;
263     for(y=0;y<8;y++) {
264         for(x=0;x<8;x++) {
265             bb->u[u++] = (p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4;
266             bb->v[v++] = (p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4;
267             bb->y1[y1++] = p1[x].y;
268             bb->y2[y2++] = p1[x+8].y;
269             bb->y3[y3++] = p1[linex*8+x].y;
270             bb->y4[y4++] = p1[linex*8+x+8].y;
271         }
272         p1+=linex;
273         p2+=linex*2;
274     }
275 }
276
277 static void getmvdregion(block_t* bb, YUV*pic, int posx, int posy, int mvdx, int mvdy, int linex)
278 {
279     YUV*p1;
280     YUV*p2;
281     int yy=0,uv=0;
282     int x,y;
283     int yhp = 0, uvhp=0;
284     int uvposx, uvposy;
285     posx = posx*16 + ((mvdx&~1)/2);
286     posy = posy*16 + ((mvdy&~1)/2);
287     p1 = &pic[posy*linex+posx];
288     p2 = &pic[(posy&~1)*linex+(posx&~1)];
289     uvhp = ((mvdx&1)|((mvdx>>1)&1))|((mvdy&2)|((mvdy&1)<<1));
290     yhp = ((mvdy&1)<<1|(mvdx&1));
291
292     /* y */
293     if(yhp==0 || yhp==2) {
294         for(y=0;y<8;y++) {
295             for(x=0;x<8;x++) {
296                 bb->y1[yy] = p1[x].y;
297                 bb->y2[yy] = p1[x+8].y;
298                 bb->y3[yy] = p1[linex*8+x].y;
299                 bb->y4[yy] = p1[linex*8+x+8].y;
300                 yy++;
301             }
302             p1+=linex;
303
304             if(yhp==2) {
305                 yy-=8;
306                 for(x=0;x<8;x++) {
307                     bb->y1[yy] += p1[x].y; bb->y1[yy] /= 2;
308                     bb->y2[yy] += p1[x+8].y; bb->y2[yy] /= 2;
309                     bb->y3[yy] += p1[linex*8+x].y; bb->y3[yy] /= 2;
310                     bb->y4[yy] += p1[linex*8+x+8].y; bb->y4[yy] /= 2;
311                     yy++;
312                 }
313             }
314         }
315     } else if(yhp==1 || yhp==3) {
316         for(y=0;y<8;y++) {
317             for(x=0;x<8;x++) {
318                 bb->y1[yy] = (p1[x].y + p1[x+1].y);
319                 bb->y2[yy] = (p1[x+8].y + p1[x+8+1].y);
320                 bb->y3[yy] = (p1[linex*8+x].y + p1[linex*8+x+1].y);
321                 bb->y4[yy] = (p1[linex*8+x+8].y + p1[linex*8+x+8+1].y);
322                 yy++;
323             }
324             yy-=8;
325             p1+=linex;
326             if(yhp==3) {
327                 for(x=0;x<8;x++) {
328                     bb->y1[yy] += (p1[x].y + p1[x+1].y); bb->y1[yy]/=4;
329                     bb->y2[yy] += (p1[x+8].y + p1[x+8+1].y); bb->y2[yy]/=4;
330                     bb->y3[yy] += (p1[linex*8+x].y + p1[linex*8+x+1].y); bb->y3[yy]/=4;
331                     bb->y4[yy] += (p1[linex*8+x+8].y + p1[linex*8+x+8+1].y); bb->y4[yy]/=4;
332                     yy++;
333                 }
334             } else {
335                 for(x=0;x<8;x++) {
336                     bb->y1[yy]/=2; bb->y2[yy]/=2; bb->y3[yy]/=2; bb->y4[yy]/=2;
337                     yy++;
338                 }
339             }
340         }
341     }
342
343     /* u,v */
344     if(uvhp==0 || uvhp==2) {
345         for(y=0;y<8;y++) {
346             for(x=0;x<8;x++) {
347                 bb->u[uv] = (p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4;
348                 bb->v[uv] = (p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4;
349                 uv++;
350             }
351             p2+=linex*2;
352             if(uvhp==2) {
353                 uv-=8;
354                 for(x=0;x<8;x++) {
355                     bb->u[uv] += (p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4;
356                     bb->v[uv] += (p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4;
357                     bb->u[uv] /= 2;
358                     bb->v[uv] /= 2;
359                     uv++;
360                 }
361             }
362         }
363     } else /* uvhp==1 || uvhp==3 */ {
364         for(y=0;y<8;y++) {
365             for(x=0;x<8;x++) {
366                 bb->u[uv] = ((p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4+
367                              (p2[x*2+2].u + p2[x*2+1+2].u + p2[linex+x*2+2].u + p2[linex+x*2+1+2].u)/4);
368                 bb->v[uv] = ((p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4+
369                              (p2[x*2+2].v + p2[x*2+1+2].v + p2[linex+x*2+2].v + p2[linex+x*2+1+2].v)/4);
370                 uv++;
371             }
372             uv-=8;
373             p2+=linex*2;
374             if(uvhp==3) {
375                 for(x=0;x<8;x++) {
376                     bb->u[uv] += ((p2[x*2].u + p2[x*2+1].u + p2[linex+x*2].u + p2[linex+x*2+1].u)/4+
377                                   (p2[x*2+2].u + p2[x*2+1+2].u + p2[linex+x*2+2].u + p2[linex+x*2+1+2].u)/4);
378                     bb->v[uv] += ((p2[x*2].v + p2[x*2+1].v + p2[linex+x*2].v + p2[linex+x*2+1].v)/4+
379                                   (p2[x*2+2].v + p2[x*2+1+2].v + p2[linex+x*2+2].v + p2[linex+x*2+1+2].v)/4);
380                     bb->u[uv] /= 4;
381                     bb->v[uv] /= 4;
382                     uv++;
383                 }
384             } else {
385                 for(x=0;x<8;x++) {
386                     bb->u[uv] /= 2;
387                     bb->v[uv] /= 2;
388                     uv++;
389                 }
390             }
391         }
392     }
393 }
394
395 static void rgb2yuv(YUV*dest, RGBA*src, int dlinex, int slinex, int width, int height)
396 {
397     int x,y;
398     for(y=0;y<height;y++) {
399         for(x=0;x<width;x++) {
400             int r,g,b;
401             r = src[y*slinex+x].r;
402             g = src[y*slinex+x].g;
403             b = src[y*slinex+x].b;
404             /*dest[y*dlinex+x].y = (r*0.299 + g*0.587 + b*0.114);
405             dest[y*dlinex+x].u = (r*-0.169 + g*-0.332 + b*0.500 + 128.0);
406             dest[y*dlinex+x].v = (r*0.500 + g*-0.419 + b*-0.0813 + 128.0);*/
407
408             //dest[y*dlinex+x].y = 128;//(r*((int)( 0.299*256)) + g*((int)( 0.587*256)) + b*((int)( 0.114 *256)))>>8;
409             dest[y*dlinex+x].y = (r*((int)( 0.299*256)) + g*((int)( 0.587*256)) + b*((int)( 0.114 *256)))>>8;
410             dest[y*dlinex+x].u = (r*((int)(-0.169*256)) + g*((int)(-0.332*256)) + b*((int)( 0.500 *256))+ 128*256)>>8;
411             dest[y*dlinex+x].v = (r*((int)( 0.500*256)) + g*((int)(-0.419*256)) + b*((int)(-0.0813*256))+ 128*256)>>8;
412         }
413     }
414 }
415 static void copyregion(VIDEOSTREAM*s, YUV*dest, YUV*src, int bx, int by)
416 {
417     YUV*p1 = &src[by*s->linex*16+bx*16];
418     YUV*p2 = &dest[by*s->linex*16+bx*16];
419     int y;
420     for(y=0;y<16;y++) {
421         memcpy(p1, p2, 16*sizeof(YUV));
422         p1+=s->linex;p2+=s->linex;
423     }
424 }
425
426 static void yuv2rgb(RGBA*dest, YUV*src, int linex, int width, int height)
427 {
428     int x,y;
429     for(y=0;y<height;y++) {
430         for(x=0;x<width;x++) {
431             int u,v,yy;
432             u = src[y*linex+x].u;
433             v = src[y*linex+x].v;
434             yy = src[y*linex+x].y;
435             dest[y*linex+x].r = truncate256(yy + ((360*(v-128))>>8));
436             dest[y*linex+x].g = truncate256(yy - ((88*(u-128)+183*(v-128))>>8));
437             dest[y*linex+x].b = truncate256(yy + ((455 * (u-128))>>8));
438         }
439     }
440 }
441 static void copyblock(VIDEOSTREAM*s, YUV*dest, block_t*b, int bx, int by)
442 {
443     YUV*p1 = &dest[(by*16)*s->linex+bx*16];
444     YUV*p2 = &dest[(by*16+8)*s->linex+bx*16];
445     int x,y;
446     for(y=0;y<8;y++) {
447         for(x=0;x<8;x++) {
448             int u,v,yy;
449             p1[x+0].u = b->u[(y/2)*8+(x/2)];
450             p1[x+0].v = b->v[(y/2)*8+(x/2)];
451             p1[x+0].y = b->y1[y*8+x];
452             p1[x+8].u = b->u[(y/2)*8+(x/2)+4];
453             p1[x+8].v = b->v[(y/2)*8+(x/2)+4];
454             p1[x+8].y = b->y2[y*8+x];
455             p2[x+0].u = b->u[(y/2+4)*8+(x/2)];
456             p2[x+0].v = b->v[(y/2+4)*8+(x/2)];
457             p2[x+0].y = b->y3[y*8+x];
458             p2[x+8].u = b->u[(y/2+4)*8+(x/2)+4];
459             p2[x+8].v = b->v[(y/2+4)*8+(x/2)+4];
460             p2[x+8].y = b->y4[y*8+x];
461         }
462         p1+=s->linex;
463         p2+=s->linex;
464     }
465 }
466
467 static int compareregions(VIDEOSTREAM*s, int bx, int by)
468 {
469     int linex = s->width;
470     YUV*p1 = &s->current[by*linex*16+bx*16];
471     YUV*p2 = &s->oldpic[by*linex*16+bx*16];
472     int diff = 0;
473     int x,y;
474     for(y=0;y<16;y++) {
475         for(x=0;x<16;x++) {
476             YUV*m = &p1[x];
477             YUV*n = &p2[x];
478             int y = m->y - n->y;
479             int u = m->u - n->u;
480             int v = m->v - n->v;
481             diff += y*y+(u*u+v*v)/4;
482         }
483         p1+=linex;
484         p2+=linex;
485     }
486     return diff/256;
487 }
488
489 static inline int valtodc(int val)
490 {
491     assert(val>=0);
492
493     /* table 12/h.263 */
494
495     //val+=4; //round
496     val/=8;
497     /* TODO: what to do for zero values? skip the block? */
498     if(val==0)
499         return 1;
500     if(val==128)
501         return 255;
502     if(val>254)
503         return 254;
504     return val;
505 }
506 static int dctoval(int dc)
507 {
508     int val;
509     assert(dc>0);
510     assert(dc!=128);
511     assert(dc<256);
512     /* table 12/h.263 */
513     val = dc*8;
514     if(val == 255*8)
515         val = 128*8;
516     return val;
517 }
518
519 static int codehuffman(TAG*tag, struct huffcode*table, int index)
520 {
521     /* TODO: !optimize! */
522     int i=0;
523     while(table[index].code[i]) {
524         if(table[index].code[i]=='0')
525             swf_SetBits(tag, 0, 1);
526         else
527             swf_SetBits(tag, 1, 1);
528         i++;
529     }
530     return i;
531 }
532
533 static void quantize8x8(int*src, int*dest, int has_dc, int quant)
534 {
535     int t,pos=0;
536     double q = 1.0/(quant*2);
537     if(has_dc) {
538         dest[0] = valtodc((int)src[0]); /*DC*/
539         pos++;
540     }
541     for(t=pos;t<64;t++)
542     {
543         //dest[t] = (int)src[t];
544     /* exact: if(quant&1){dest[t] = (dest[t]/quant - 1)/2;}else{dest[t] = ((dest[t]+1)/quant - 1)/2;} */
545         //if(quant&1){dest[t] = (dest[t]/quant - 1)/2;}else{dest[t] = ((dest[t]+1)/quant - 1)/2;}
546         //dest[t] = dest[t]/(quant*2);
547         dest[t] = (int)(src[t]*q);
548         /* TODO: warn if this happens- the video will be buggy */
549         if(dest[t]>127) dest[t]=127;
550         if(dest[t]<-127) dest[t]=-127;
551     }
552 }
553
554 static void dequantize8x8(int*b, int has_dc, int quant)
555 {
556     int t,pos=0;
557     if(has_dc) {
558         b[0] = dctoval(b[0]); //DC
559         pos++;
560     }
561     for(t=pos;t<64;t++) {
562         if(b[t]) {
563             int sign = 0;
564             if(b[t]<0) {
565                 b[t] = -b[t];
566                 sign = 1;
567             }
568
569             if(quant&1) {
570                 b[t] = quant*(2*b[t]+1); //-7,8,24,40
571             } else {
572                 b[t] = quant*(2*b[t]+1)-1; //-8,7,23,39
573             }
574
575             if(sign)
576                 b[t] = -b[t];
577         }
578
579         /* paragraph 6.2.2, "clipping of reconstruction levels": */
580         if(b[t]>2047) b[t]=2047;
581         if(b[t]<-2048) b[t]=-2048;
582     }
583 }
584
585 static int hascoef(int*b, int has_dc)
586 {
587     int t;
588     int pos=0;
589     if(has_dc)
590         pos++;
591     for(t=pos;t<64;t++) {
592         if(b[t])
593             return 1;
594     }
595     return 0;
596 }
597
598 static int coefbits8x8(int*bb, int has_dc)
599 {
600     int t;
601     int pos=0;
602     int bits=0;
603     int last;
604
605     if(has_dc) {
606         bits+=8;
607         pos++;
608     }
609     for(last=63;last>=pos;last--) {
610         if(bb[last])
611             break;
612     }
613     if(last < pos)
614         return bits;
615     while(1) {
616         int run=0, level=0, islast=0,t;
617         while(!bb[pos] && pos<last) {
618             pos++;
619             run++;
620         }
621         if(pos==last)
622             islast=1;
623         level=bb[pos];
624         if(level<0) level=-level;
625         assert(level);
626         for(t=0;t<RLE_ESCAPE;t++) {
627             if(rle_params[t].run == run &&
628                rle_params[t].level == level &&
629                rle_params[t].last == islast) {
630                 bits += rle[t].len + 1;
631                 break;
632             }
633         }
634         if(t==RLE_ESCAPE) {
635             bits += rle[RLE_ESCAPE].len + 1 + 6 + 8;
636         }
637         if(islast)
638             break;
639         pos++;
640     }
641     return bits;
642 }
643
644 static void encode8x8(TAG*tag, int*bb, int has_dc, int has_tcoef)
645 {
646     int t;
647     int pos=0;
648     int bits=0;
649
650     if(has_dc) {
651         swf_SetBits(tag, bb[0], 8);
652         pos++;
653     }
654
655     if(has_tcoef) {
656         int last;
657         /* determine last non-null coefficient */
658         for(last=63;last>=pos;last--) {
659             /* TODO: we could leave out small coefficients
660                      after a certain point (32?) */
661             if(bb[last])
662                 break;
663         }
664         /* blocks without coefficients should not be included
665            in the cbpy/cbpc patterns: */
666         assert(bb[last]);
667
668         while(1) {
669             int run=0;
670             int level=0;
671             int islast=0;
672             int sign=0;
673             int t;
674             while(!bb[pos] && pos<last) {
675                 pos++;
676                 run++;
677             }
678             if(pos==last)
679                 islast=1;
680             level=bb[pos];
681             assert(level);
682             if(level<0) {
683                 level = -level;
684                 sign = 1;
685             }
686             for(t=0;t<RLE_ESCAPE;t++) {
687                 /* TODO: lookup table */
688                 if(rle_params[t].run == run &&
689                    rle_params[t].level == level &&
690                    rle_params[t].last == islast) {
691                     codehuffman(tag, rle, t);
692                     swf_SetBits(tag, sign, 1);
693                     break;
694                 }
695             }
696             if(t==RLE_ESCAPE) {
697                 codehuffman(tag, rle, RLE_ESCAPE);
698                 level=bb[pos];
699                 /* table 14/h.263 */
700                 assert(level);
701                 assert(level>=-127);
702                 assert(level<=127);
703
704                 swf_SetBits(tag, islast, 1);
705                 swf_SetBits(tag, run, 6);
706                 swf_SetBits(tag, level, 8); //FIXME: fixme??
707             }
708
709             if(islast)
710                 break;
711             pos++;
712         }
713     }
714 }
715
716 static void quantize(block_t*fb, block_t*b, int has_dc, int quant)
717 {
718     quantize8x8(fb->y1, b->y1, has_dc, quant);
719     quantize8x8(fb->y2, b->y2, has_dc, quant);
720     quantize8x8(fb->y3, b->y3, has_dc, quant);
721     quantize8x8(fb->y4, b->y4, has_dc, quant);
722     quantize8x8(fb->u, b->u, has_dc, quant);
723     quantize8x8(fb->v, b->v, has_dc, quant);
724 }
725
726 static void dodct(block_t*fb)
727 {
728     dct(fb->y1); dct(fb->y2); dct(fb->y3); dct(fb->y4);
729     dct(fb->u);  dct(fb->v);
730     zigzag(fb->y1);
731     zigzag(fb->y2);
732     zigzag(fb->y3);
733     zigzag(fb->y4);
734     zigzag(fb->u);
735     zigzag(fb->v);
736 }
737 static void dodctandquant(block_t*fb, block_t*b, int has_dc, int quant)
738 {
739     int t;
740     if(has_dc) {
741         dodct(fb);
742         quantize(fb,b,has_dc,quant);
743         return;
744     }
745     preparequant(quant);
746     dct2(fb->y1,b->y1); dct2(fb->y2,b->y2); dct2(fb->y3,b->y3); dct2(fb->y4,b->y4);
747     dct2(fb->u,b->u);  dct2(fb->v,b->v);
748 }
749
750 static void doidct(block_t*b)
751 {
752     block_t fb;
753     int t;
754     for(t=0;t<64;t++) {
755         fb.y1[t] = b->y1[zigzagtable[t]];
756         fb.y2[t] = b->y2[zigzagtable[t]];
757         fb.y3[t] = b->y3[zigzagtable[t]];
758         fb.y4[t] = b->y4[zigzagtable[t]];
759         fb.u[t] = b->u[zigzagtable[t]];
760         fb.v[t] = b->v[zigzagtable[t]];
761     }
762     idct(fb.y1); idct(fb.y2); idct(fb.y3); idct(fb.y4);
763     idct(fb.u);  idct(fb.v);
764     for(t=0;t<64;t++) {
765         b->y1[t] = fb.y1[t];
766         b->y2[t] = fb.y2[t];
767         b->y3[t] = fb.y3[t];
768         b->y4[t] = fb.y4[t];
769         b->u[t] = fb.u[t];
770         b->v[t] = fb.v[t];
771     }
772 }
773 static void truncateblock(block_t*b)
774 {
775     int t;
776     for(t=0;t<64;t++) {
777         b->y1[t] = truncate256(b->y1[t]);
778         b->y2[t] = truncate256(b->y2[t]);
779         b->y3[t] = truncate256(b->y3[t]);
780         b->y4[t] = truncate256(b->y4[t]);
781         b->u[t] = truncate256(b->u[t]);
782         b->v[t] = truncate256(b->v[t]);
783     }
784 }
785
786 static void dequantize(block_t*b, int has_dc, int quant)
787 {
788     dequantize8x8(b->y1, has_dc, quant);
789     dequantize8x8(b->y2, has_dc, quant);
790     dequantize8x8(b->y3, has_dc, quant);
791     dequantize8x8(b->y4, has_dc, quant);
792     dequantize8x8(b->u, has_dc, quant);
793     dequantize8x8(b->v, has_dc, quant);
794 }
795
796 static void getblockpatterns(block_t*b, int*cbpybits,int*cbpcbits, int has_dc)
797 {
798     *cbpybits = 0;
799     *cbpcbits = 0;
800
801     *cbpybits|=hascoef(b->y1, has_dc)*8;
802     *cbpybits|=hascoef(b->y2, has_dc)*4;
803     *cbpybits|=hascoef(b->y3, has_dc)*2;
804     *cbpybits|=hascoef(b->y4, has_dc)*1;
805
806     *cbpcbits|=hascoef(b->u, has_dc)*2;
807     *cbpcbits|=hascoef(b->v, has_dc)*1;
808 }
809
810 static void setQuant(TAG*tag, int dquant)
811 {
812     int code = 0;
813     /* 00 01 10 11
814        -1 -2 +1 +2
815     */
816     if(dquant == -1) {
817         swf_SetBits(tag, 0x0, 2);
818     } else if(dquant == -2) {
819         swf_SetBits(tag, 0x1, 2);
820     } else if(dquant == +1) {
821         swf_SetBits(tag, 0x2, 2);
822     } else if(dquant == +2) {
823         swf_SetBits(tag, 0x3, 2);
824     } else {
825         assert(0*strlen("invalid dquant"));
826     }
827 }
828
829 static void change_quant(int quant, int*dquant)
830 {
831     /* TODO */
832     *dquant = 0;
833 }
834
835 static void encode_blockI(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant)
836 {
837     block_t fb;
838     block_t b;
839     int dquant=0;
840     int cbpcbits = 0, cbpybits=0;
841
842     getregion(&fb, s->current, bx, by, s->width);
843
844     change_quant(*quant, &dquant);
845     *quant+=dquant;
846
847     dodctandquant(&fb, &b, 1, *quant);
848     //quantize(&fb, &b, 1, *quant);
849
850     //decode_blockI(s, &b, bx, by);
851
852     getblockpatterns(&b, &cbpybits, &cbpcbits, 1);
853
854     if(dquant) {
855         codehuffman(tag, mcbpc_intra, 4+cbpcbits);
856     } else {
857         codehuffman(tag, mcbpc_intra, 0+cbpcbits);
858     }
859
860     codehuffman(tag, cbpy, cbpybits);
861
862     if(dquant) {
863         setQuant(tag, dquant);
864     }
865
866     /* luminance */
867     encode8x8(tag, b.y1, 1, cbpybits&8);
868     encode8x8(tag, b.y2, 1, cbpybits&4);
869     encode8x8(tag, b.y3, 1, cbpybits&2);
870     encode8x8(tag, b.y4, 1, cbpybits&1);
871
872     /* chrominance */
873     encode8x8(tag, b.u, 1, cbpcbits&2);
874     encode8x8(tag, b.v, 1, cbpcbits&1);
875
876     /* reconstruct */
877     dequantize(&b, 1, *quant);
878     doidct(&b);
879     truncateblock(&b);
880     copyblock(s, s->current, &b, bx, by);
881 }
882
883 static void yuvdiff(block_t*a, block_t*b)
884 {
885     int t;
886     for(t=0;t<64;t++) {
887         a->y1[t] = (a->y1[t] - b->y1[t]);
888         a->y2[t] = (a->y2[t] - b->y2[t]);
889         a->y3[t] = (a->y3[t] - b->y3[t]);
890         a->y4[t] = (a->y4[t] - b->y4[t]);
891         a->u[t]  = (a->u[t] - b->u[t]);
892         a->v[t]  = (a->v[t] - b->v[t]);
893     }
894 }
895
896 static void predictmvd(VIDEOSTREAM*s, int bx, int by, int*px, int*py)
897 {
898     int i1,i2;
899     int x1,y1,x2,y2,x3,y3;
900     int x4,y4,p;
901     if(bx) {x1=s->mvdx[by*s->bbx+bx-1];
902             y1=s->mvdy[by*s->bbx+bx-1];
903     } else {x1=y1=0;}
904
905     if(by) {x2=s->mvdx[(by-1)*s->bbx+bx];
906             y2=s->mvdy[(by-1)*s->bbx+bx];
907             if(bx<s->bbx-1) {
908                 x3=s->mvdx[(by-1)*s->bbx+bx+1];
909                 y3=s->mvdy[(by-1)*s->bbx+bx+1];
910             } else {
911                 x3=y3=0;
912             }
913            }
914     else   {x2=x3=x1;y2=y3=y1;}
915
916            if((x1 <= x2 && x2 <= x3) ||
917               (x3 <= x2 && x2 <= x1)) {
918         x4=x2;
919     } else if((x2 <= x1 && x1 <= x3) ||
920               (x3 <= x1 && x1 <= x2)) {
921         x4=x1;
922     } else if((x1 <= x3 && x3 <= x2) ||
923               (x2 <= x3 && x3 <= x1)) {
924         x4=x3;
925     }
926
927            if((y1 <= y2 && y2 <= y3) ||
928               (y3 <= y2 && y2 <= y1)) {
929         y4=y2;
930     } else if((y2 <= y1 && y1 <= y3) ||
931               (y3 <= y1 && y1 <= y2)) {
932         y4=y1;
933     } else if((y1 <= y3 && y3 <= y2) ||
934               (y2 <= y3 && y3 <= y1)) {
935         y4=y3;
936     }
937
938     *px = x4;
939     *py = y4;
940     assert((x4>=-32 && x4<=31) && (y4>=-32 && y4<=31));
941 }
942
943 static inline int mvd2index(int px, int py, int x, int y, int xy)
944 {
945     assert((x>=-32 && x<=31) && (y>=-32 && y<=31));
946     //assert((x&1)==0 && (y&1)==0);//for now
947     //assert((x&2)==0 && (y&2)==0);//for now(2)
948
949     x-=px;
950     y-=py;
951
952     if(xy)
953         x=y;
954     x+=32;
955
956     /* (x&63) */
957     if(x>63)
958         x-=64;
959     if(x<0)
960         x+=64;
961
962     assert(x>=0 && x<64);
963     return x;
964 }
965
966 static int encode_blockP(TAG*tag, VIDEOSTREAM*s, int bx, int by, int*quant)
967 {
968     block_t fb;
969     block_t b;
970     int dquant=0;
971     int has_mvd=0;
972     int has_mvd24=0;
973     int has_dc=1;
974     int mode = 0;
975     int cbpcbits = 0, cbpybits=0;
976     int diff;
977     int predictmvdx;
978     int predictmvdy;
979
980     block_t b_i;
981     int bits_i;
982
983     block_t fbold_v00;
984     block_t b_v00;
985     int bits_v00 = 65535;
986     int x_v00=0;
987     int y_v00=0;
988
989     diff = compareregions(s, bx, by);
990
991     if(diff < 20 /*TODO: should be a parameter- good values are between 32 and 48 */) {
992         /* TODO: measure the error an I-block encoding would do, and base the decision
993            on that */
994         swf_SetBits(tag, 1,1); /* cod=1, block skipped */
995         /* copy the region from the last frame so that we have a complete reconstruction */
996         copyregion(s, s->current, s->oldpic, bx, by);
997         return 1;
998     }
999
1000     predictmvd(s,bx,by,&predictmvdx,&predictmvdy);
1001     getregion(&fb, s->current, bx, by, s->width);
1002
1003     { /* consider I-block */
1004         block_t fb_i;
1005         int y,c;
1006         memcpy(&fb_i, &fb, sizeof(block_t));
1007         dodctandquant(&fb_i, &b_i, 1, *quant);
1008         //quantize(&fb_i, &b_i, 1, *quant);
1009         getblockpatterns(&b_i, &y, &c, 1);
1010         bits_i = 1; //cod
1011         bits_i += mcbpc_inter[3*4+c].len;
1012         bits_i += cbpy[y].len;
1013         bits_i += coefbits8x8(b_i.y1, 1);
1014         bits_i += coefbits8x8(b_i.y2, 1);
1015         bits_i += coefbits8x8(b_i.y3, 1);
1016         bits_i += coefbits8x8(b_i.y4, 1);
1017         bits_i += coefbits8x8(b_i.u, 1);
1018         bits_i += coefbits8x8(b_i.v, 1);
1019     }
1020
1021     { /* consider mvd(x,y)-block */
1022         block_t fbdiff;
1023         int y,c;
1024
1025         x_v00=0;
1026         y_v00=0;
1027
1028         if(s->do_motion) {
1029             int hx,hy;
1030             int bestx=0,besty=0,bestbits=65536;
1031             int startx=-2,endx=2;
1032             int starty=-2,endy=2;
1033
1034             if(!bx) startx=0;
1035             if(!by) starty=0;
1036             if(bx==s->bbx-1) endx=0;
1037             if(by==s->bby-1) endy=0;
1038
1039             for(hx=startx;hx<=endx;hx+=1)
1040             for(hy=starty;hy<=endy;hy+=1)
1041             {
1042                 block_t b;
1043                 block_t fbold;
1044                 int bits = 0;
1045                 memcpy(&fbdiff, &fb, sizeof(block_t));
1046                 getmvdregion(&fbold, s->oldpic, bx, by, hx, hy, s->linex);
1047                 yuvdiff(&fbdiff, &fbold);
1048                 dodctandquant(&fbdiff, &b, 0, *quant);
1049                 //quantize(&fbdiff, &b, 0, *quant);
1050                 bits += coefbits8x8(b.y1, 0);
1051                 bits += coefbits8x8(b.y2, 0);
1052                 bits += coefbits8x8(b.y3, 0);
1053                 bits += coefbits8x8(b.y4, 0);
1054                 bits += coefbits8x8(b.u, 0);
1055                 bits += coefbits8x8(b.v, 0);
1056                 if(bits<bestbits) {
1057                     bestbits = bits;
1058                     bestx = hx;
1059                     besty = hy;
1060                 }
1061             }
1062             x_v00 = bestx;
1063             y_v00 = besty;
1064         }
1065
1066         memcpy(&fbdiff, &fb, sizeof(block_t));
1067         getmvdregion(&fbold_v00, s->oldpic, bx, by, x_v00, y_v00, s->linex);
1068         yuvdiff(&fbdiff, &fbold_v00);
1069         dodctandquant(&fbdiff, &b_v00, 0, *quant);
1070         //quantize(&fbdiff, &b_v00, 0, *quant);
1071         getblockpatterns(&b_v00, &y, &c, 0);
1072
1073         bits_v00 = 1; //cod
1074         bits_v00 += mcbpc_inter[0*4+c].len;
1075         bits_v00 += cbpy[y^15].len;
1076         bits_v00 += mvd[mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 0)].len; // (0,0)
1077         bits_v00 += mvd[mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 1)].len;
1078         bits_v00 += coefbits8x8(b_v00.y1, 0);
1079         bits_v00 += coefbits8x8(b_v00.y2, 0);
1080         bits_v00 += coefbits8x8(b_v00.y3, 0);
1081         bits_v00 += coefbits8x8(b_v00.y4, 0);
1082         bits_v00 += coefbits8x8(b_v00.u, 0);
1083         bits_v00 += coefbits8x8(b_v00.v, 0);
1084     }
1085
1086     if(bits_i > bits_v00)
1087     {
1088         /* mvd (0,0) block (mode=0) */
1089         int t;
1090         mode = 0; // mvd w/o mvd24
1091         has_dc = 0;
1092         memcpy(&b, &b_v00, sizeof(block_t));
1093
1094         getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
1095         swf_SetBits(tag,0,1); // COD
1096         codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
1097         codehuffman(tag, cbpy, cbpybits^15);
1098
1099         /* vector */
1100         codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 0));
1101         codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, x_v00, y_v00, 1));
1102         s->mvdx[by*s->bbx+bx] = x_v00;
1103         s->mvdy[by*s->bbx+bx] = y_v00;
1104
1105         /* luminance */
1106         encode8x8(tag, b.y1, has_dc, cbpybits&8);
1107         encode8x8(tag, b.y2, has_dc, cbpybits&4);
1108         encode8x8(tag, b.y3, has_dc, cbpybits&2);
1109         encode8x8(tag, b.y4, has_dc, cbpybits&1);
1110
1111         /* chrominance */
1112         encode8x8(tag, b.u, has_dc, cbpcbits&2);
1113         encode8x8(tag, b.v, has_dc, cbpcbits&1);
1114
1115         /* -- reconstruction -- */
1116         dequantize(&b, 0, *quant);
1117         doidct(&b);
1118         for(t=0;t<64;t++) {
1119             b.y1[t] = truncate256(b.y1[t] + (int)fbold_v00.y1[t]);
1120             b.y2[t] = truncate256(b.y2[t] + (int)fbold_v00.y2[t]);
1121             b.y3[t] = truncate256(b.y3[t] + (int)fbold_v00.y3[t]);
1122             b.y4[t] = truncate256(b.y4[t] + (int)fbold_v00.y4[t]);
1123             b.u[t] = truncate256(b.u[t] + (int)fbold_v00.u[t]);
1124             b.v[t] = truncate256(b.v[t] + (int)fbold_v00.v[t]);
1125         }
1126         copyblock(s, s->current, &b, bx, by);
1127         return bits_v00;
1128     } else {
1129         /* i block (mode=3) */
1130         mode = 3;
1131         has_dc = 1;
1132         memcpy(&b, &b_i, sizeof(block_t));
1133         getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
1134         swf_SetBits(tag,0,1); // COD
1135         codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
1136         codehuffman(tag, cbpy, cbpybits);
1137
1138         /* luminance */
1139         encode8x8(tag, b.y1, has_dc, cbpybits&8);
1140         encode8x8(tag, b.y2, has_dc, cbpybits&4);
1141         encode8x8(tag, b.y3, has_dc, cbpybits&2);
1142         encode8x8(tag, b.y4, has_dc, cbpybits&1);
1143
1144         /* chrominance */
1145         encode8x8(tag, b.u, has_dc, cbpcbits&2);
1146         encode8x8(tag, b.v, has_dc, cbpcbits&1);
1147
1148         /* -- reconstruction -- */
1149         dequantize(&b, 1, *quant);
1150         doidct(&b);
1151         truncateblock(&b);
1152         copyblock(s, s->current, &b, bx, by);
1153         return bits_i;
1154     }
1155
1156     exit(1);
1157 #if 0
1158     dodct(&fb);
1159     quantize(&fb, &b, has_dc, *quant);
1160     getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
1161
1162     if(!dquant && has_mvd && !has_mvd24 && !has_dc) mode = 0;
1163     else if(dquant && has_mvd && !has_mvd24 && !has_dc) mode = 1;
1164     else if(!dquant && has_mvd && has_mvd24 && !has_dc) mode = 2;
1165     else if(!dquant && !has_mvd && !has_mvd24 && has_dc) mode = 3;
1166     else if(dquant && !has_mvd && !has_mvd24 && has_dc) mode = 4;
1167     else exit(1);
1168
1169     swf_SetBits(tag,0,1); /* cod - 1 if we're not going to code this block*/
1170
1171     codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
1172     codehuffman(tag, cbpy, (mode==3 || mode==4)?cbpybits:cbpybits^15);
1173
1174     if(dquant) {
1175         setQuant(tag, dquant);
1176     }
1177
1178     if(has_mvd) {
1179         /* 0,0 */
1180         codehuffman(tag, mvd, 32);
1181         codehuffman(tag, mvd, 32);
1182     }
1183     if(has_mvd24) {
1184     }
1185
1186     /* luminance */
1187     encode8x8(tag, b.y1, has_dc, cbpybits&8);
1188     encode8x8(tag, b.y2, has_dc, cbpybits&4);
1189     encode8x8(tag, b.y3, has_dc, cbpybits&2);
1190     encode8x8(tag, b.y4, has_dc, cbpybits&1);
1191
1192     /* chrominance */
1193     encode8x8(tag, b.u, has_dc, cbpcbits&2);
1194     encode8x8(tag, b.v, has_dc, cbpcbits&1);
1195 #endif
1196 }
1197
1198 static int bmid = 0;
1199 void setdbgpic(TAG*tag, RGBA*pic, int width, int height)
1200 {
1201     MATRIX m;
1202     tag = tag->prev;
1203
1204     tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1205     swf_SetU16(tag, 133);
1206
1207     tag = swf_InsertTag(tag, ST_DEFINEBITSLOSSLESS);
1208     swf_SetU16(tag, 1000+bmid);
1209     swf_SetLosslessBits(tag, width, height, (void*)pic, BMF_32BIT);
1210
1211     tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1212     swf_SetU16(tag, 2000+bmid);
1213     swf_ShapeSetBitmapRect(tag, 1000+bmid, width, height);
1214
1215     tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1216     swf_GetMatrix(0,&m);
1217     m.tx = width*20;
1218     swf_ObjectPlace(tag, 2000+bmid, 133, &m, 0, 0);
1219
1220     bmid++;
1221 }
1222
1223 #define TYPE_IFRAME 0
1224 #define TYPE_PFRAME 1
1225
1226 static void writeHeader(TAG*tag, int width, int height, int frame, int quant, int type)
1227 {
1228     U32 i32;
1229     swf_SetU16(tag, frame);
1230     swf_SetBits(tag, 1, 17); /* picture start code*/
1231     swf_SetBits(tag, 0, 5); /* version=0, version 1 would optimize rle behaviour*/
1232     swf_SetBits(tag, frame, 8); /* time reference */
1233
1234     /* write dimensions, taking advantage of some predefined sizes
1235        if the opportunity presents itself */
1236     i32 = width<<16|height;
1237     switch(i32)
1238     {
1239         case 352<<16|288: swf_SetBits(tag, 2, 3);break;
1240         case 176<<16|144: swf_SetBits(tag, 3, 3);break;
1241         case 128<<16|96: swf_SetBits(tag, 4, 3);break;
1242         case 320<<16|240: swf_SetBits(tag, 5, 3);break;
1243         case 160<<16|120: swf_SetBits(tag, 6, 3);break;
1244         default:
1245             if(width>255 || height>255) {
1246                 swf_SetBits(tag, 1, 3);
1247                 swf_SetBits(tag, width, 16);
1248                 swf_SetBits(tag, height, 16);
1249             } else {
1250                 swf_SetBits(tag, 0, 3);
1251                 swf_SetBits(tag, width, 8);
1252                 swf_SetBits(tag, height, 8);
1253             }
1254     }
1255
1256     swf_SetBits(tag, type, 2); /* I-Frame or P-Frame */
1257     swf_SetBits(tag, 0, 1); /* No deblock filter */
1258     assert(quant>0);
1259     swf_SetBits(tag, quant, 5); /* quantizer (1-31), may be updated later on*/
1260     swf_SetBits(tag, 0, 1); /* No extra info */
1261 }
1262
1263 void swf_SetVideoStreamIFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
1264 {
1265     int bx, by;
1266
1267     if(quant<1) quant=1;
1268     if(quant>31) quant=31;
1269
1270     writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_IFRAME);
1271
1272     rgb2yuv(s->current, pic, s->linex, s->olinex, s->width, s->height);
1273
1274     //dostat(s);
1275
1276     for(by=0;by<s->bby;by++)
1277     {
1278         for(bx=0;bx<s->bbx;bx++)
1279         {
1280             encode_blockI(tag, s, bx, by, &quant);
1281         }
1282     }
1283     s->frame++;
1284     memcpy(s->oldpic, s->current, s->width*s->height*sizeof(YUV));
1285 }
1286
1287 void swf_SetVideoStreamPFrame(TAG*tag, VIDEOSTREAM*s, RGBA*pic, int quant)
1288 {
1289     int bx, by;
1290
1291     if(quant<1) quant=1;
1292     if(quant>31) quant=31;
1293
1294     writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_PFRAME);
1295
1296     rgb2yuv(s->current, pic, s->linex, s->olinex, s->width, s->height);
1297     memset(s->mvdx, 0, s->bbx*s->bby*sizeof(int));
1298     memset(s->mvdy, 0, s->bbx*s->bby*sizeof(int));
1299
1300     for(by=0;by<s->bby;by++)
1301     {
1302         for(bx=0;bx<s->bbx;bx++)
1303         {
1304             encode_blockP(tag, s, bx, by, &quant);
1305         }
1306     }
1307     s->frame++;
1308     memcpy(s->oldpic, s->current, s->width*s->height*sizeof(YUV));
1309
1310 //#define PNG
1311 #ifdef MAIN
1312 #ifdef PNG
1313     yuv2rgb(pic, s->current, s->linex, s->width, s->height);
1314     setdbgpic(tag, pic, s->width, s->height);
1315 #endif
1316     if(s->frame == (int)totalframes-1)
1317     {
1318         int t;
1319         FILE*fi = fopen("test.ppm", "wb");
1320         fprintf(fi, "P6\n%d %d\n255\n", s->width, s->height);
1321         for(t=0;t<s->width*s->height;t++)
1322         {
1323             fwrite(&pic[t].r, 1, 1, fi);
1324             fwrite(&pic[t].g, 1, 1, fi);
1325             fwrite(&pic[t].b, 1, 1, fi);
1326         }
1327         fclose(fi);
1328     }
1329 #endif
1330 }
1331
1332 int uline[64],vline[64],yline[64];
1333 void swf_SetVideoStreamMover(TAG*tag, VIDEOSTREAM*s, int quant)
1334 {
1335     int bx, by;
1336
1337     if(quant<1) quant=1;
1338     if(quant>31) quant=31;
1339
1340     writeHeader(tag, s->width, s->height, s->frame, quant, TYPE_PFRAME);
1341
1342     memset(s->mvdx, 0, s->bbx*s->bby*sizeof(int));
1343     memset(s->mvdy, 0, s->bbx*s->bby*sizeof(int));
1344
1345     for(by=0;by<s->bby;by++)
1346     {
1347         for(bx=0;bx<s->bbx;bx++)
1348         {
1349             //if((lrand48()&255) || !(bx>8 && bx<24 && by>8 && by<24)) {
1350             if(!(by==31)) {
1351                 /* mvd (0,0) block (mode=0) */
1352                 int t;
1353                 int mode = 0; // mvd w/o mvd24
1354                 int has_dc = 0;
1355                 int cbpybits=0,cbpcbits=0;
1356                 int predictmvdx, predictmvdy;
1357                 //int mvx=-1+(2*(s->frame&1));
1358                 //int mvy=-1+((s->frame&2));
1359                 int mvx=(lrand48()%4)-2;
1360                 int mvy=3;
1361
1362                 swf_SetBits(tag,0,1); // COD
1363                 codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
1364                 codehuffman(tag, cbpy, cbpybits^15);
1365
1366                 /* vector */
1367                 predictmvd(s,bx,by,&predictmvdx,&predictmvdy);
1368                 codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, mvx, mvy, 0));
1369                 codehuffman(tag, mvd, mvd2index(predictmvdx, predictmvdy, mvx, mvy, 1));
1370                 s->mvdx[by*s->bbx+bx] = mvx;
1371                 s->mvdy[by*s->bbx+bx] = mvy;
1372             } else {
1373                 /* i block (mode=3) */
1374                 int mode = 3;
1375                 int has_dc = 1;
1376                 int cbpybits,cbpcbits;
1377                 int t;
1378                 block_t b;
1379                 memset(&b, 0, sizeof(block_t));
1380                 b.y1[0] = b.y2[0] = b.y3[0] = b.y4[0] = yline[bx];
1381                 b.u[0] = uline[bx];
1382                 b.v[0] = vline[bx];
1383
1384                 getblockpatterns(&b, &cbpybits, &cbpcbits, has_dc);
1385                 swf_SetBits(tag,0,1); // COD
1386                 codehuffman(tag, mcbpc_inter, mode*4+cbpcbits);
1387                 codehuffman(tag, cbpy, cbpybits);
1388
1389                 /* luminance */
1390                 encode8x8(tag, b.y1, has_dc, cbpybits&8);
1391                 encode8x8(tag, b.y2, has_dc, cbpybits&4);
1392                 encode8x8(tag, b.y3, has_dc, cbpybits&2);
1393                 encode8x8(tag, b.y4, has_dc, cbpybits&1);
1394
1395                 /* chrominance */
1396                 encode8x8(tag, b.u, has_dc, cbpcbits&2);
1397                 encode8x8(tag, b.v, has_dc, cbpcbits&1);
1398             }
1399         }
1400     }
1401 }
1402
1403 #ifdef MAIN
1404 #include "png.h"
1405 int main(int argn, char*argv[])
1406 {
1407     int fi;
1408     int t;
1409     SWF swf;
1410     TAG * tag;
1411     RGBA* pic, *pic2, rgb;
1412     SWFPLACEOBJECT obj;
1413     int width = 0;
1414     int height = 0;
1415     int frames = 20;
1416     int framerate = 29;
1417     unsigned char*data;
1418     char* fname = "/home/kramm/pics/peppers.png";
1419     VIDEOSTREAM stream;
1420     double d = 1.0;
1421
1422     memset(&stream, 0, sizeof(stream));
1423
1424     getPNG(fname, &width, &height, &data);
1425     pic = (RGBA*)malloc(width*height*sizeof(RGBA));
1426     pic2 = (RGBA*)malloc(width*height*sizeof(RGBA));
1427     memcpy(pic, data, width*height*sizeof(RGBA));
1428     free(data);
1429
1430     printf("Compressing %s, size %dx%d\n", fname, width, height);
1431
1432     memset(&swf,0,sizeof(SWF));
1433     memset(&obj,0,sizeof(obj));
1434
1435     swf.fileVersion    = 6;
1436     swf.frameRate      = framerate*256;
1437     swf.movieSize.xmax = 20*width*2;
1438     swf.movieSize.ymax = 20*height-20*64;
1439
1440     swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1441     tag = swf.firstTag;
1442     rgb.r = 0x00;rgb.g = 0x00;rgb.b = 0x00;
1443     swf_SetRGB(tag,&rgb);
1444
1445     tag = swf_InsertTag(tag, ST_DEFINEVIDEOSTREAM);
1446     swf_SetU16(tag, 33);
1447     swf_SetVideoStreamDefine(tag, &stream, frames, width, height);
1448     stream.do_motion = 1;
1449
1450     for(t=0;t<frames;t++)
1451     {
1452         int x,y;
1453         double xx,yy;
1454         for(y=0,yy=0;y<height;y++,yy+=d)  {
1455             RGBA*line = &pic[((int)yy)*width];
1456             for(x=0,xx=0;x<width;x++,xx+=d) {
1457                 pic2[y*width+x] = line[((int)xx)];
1458             }
1459         }
1460         printf("frame:%d\n", t);fflush(stdout);
1461
1462         tag = swf_InsertTag(tag, ST_VIDEOFRAME);
1463         swf_SetU16(tag, 33);
1464         if(t==0)
1465             swf_SetVideoStreamIFrame(tag, &stream, pic2, 9);
1466         else {
1467             swf_SetVideoStreamPFrame(tag, &stream, pic2, 9);
1468         }
1469
1470         tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1471         swf_GetPlaceObject(0, &obj);
1472         if(t==0) {
1473             obj.depth = 1;
1474             obj.id = 33;
1475         } else {
1476             obj.move = 1;
1477             obj.depth = 1;
1478             obj.ratio = t;
1479         }
1480         swf_SetPlaceObject(tag,&obj);
1481
1482         tag = swf_InsertTag(tag, ST_SHOWFRAME);
1483         d-=0.015;
1484     }
1485     swf_VideoStreamClear(&stream);
1486
1487     tag = swf_InsertTag(tag, ST_END);
1488
1489     fi = open("video3.swf", O_WRONLY|O_CREAT|O_TRUNC, 0644);
1490     if(swf_WriteSWC(fi,&swf)<0) {
1491         fprintf(stderr,"WriteSWF() failed.\n");
1492     }
1493     close(fi);
1494     swf_FreeTags(&swf);
1495 }
1496 #undef MAIN
1497 #endif