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