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