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