alternative test video generator by (Sebastien Bechet <s dot bechet at av7 dot net>)
[ffmpeg.git] / tests / rotozoom.c
1 /*
2  * Generates a synthetic YUV video sequence suitable for codec testing.
3  * GPLv2
4  * rotozoom.c -> s.bechet@av7.net
5  */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <math.h>
9
10 #define SCALEBITS 8
11 #define ONE_HALF  (1 << (SCALEBITS - 1))
12 #define FIX(x)          ((int) ((x) * (1L<<SCALEBITS) + 0.5))
13 typedef unsigned char UINT8;
14
15 static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
16                               UINT8 *src, int width, int height)
17 {
18     int wrap, wrap3, x, y;
19     int r, g, b, r1, g1, b1;
20     UINT8 *p;
21
22     wrap = width;
23     wrap3 = width * 3;
24     p = src;
25     for(y=0;y<height;y+=2) {
26         for(x=0;x<width;x+=2) {
27             r = p[0];
28             g = p[1];
29             b = p[2];
30             r1 = r;
31             g1 = g;
32             b1 = b;
33             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
34                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
35             r = p[3];
36             g = p[4];
37             b = p[5];
38             r1 += r;
39             g1 += g;
40             b1 += b;
41             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
42                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
43             p += wrap3;
44             lum += wrap;
45
46             r = p[0];
47             g = p[1];
48             b = p[2];
49             r1 += r;
50             g1 += g;
51             b1 += b;
52             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
53                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
54             r = p[3];
55             g = p[4];
56             b = p[5];
57             r1 += r;
58             g1 += g;
59             b1 += b;
60             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
61                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
62             
63             cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
64                       FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
65             cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
66                      FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
67
68             cb++;
69             cr++;
70             p += -wrap3 + 2 * 3;
71             lum += -wrap + 2;
72         }
73         p += wrap3;
74         lum += wrap;
75     }
76 }
77
78 /* cif format */
79 #define DEFAULT_WIDTH   352
80 #define DEFAULT_HEIGHT  288
81 #define DEFAULT_NB_PICT 360
82
83 void pgmyuv_save(const char *filename, int w, int h,
84                  unsigned char *rgb_tab)
85 {
86     FILE *f;
87     int i, h2, w2;
88     unsigned char *cb, *cr;
89     unsigned char *lum_tab, *cb_tab, *cr_tab;
90
91     lum_tab = malloc(w * h);
92     cb_tab = malloc((w * h) / 4);
93     cr_tab = malloc((w * h) / 4);
94
95     rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
96
97     f = fopen(filename,"w");
98     fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255);
99     fwrite(lum_tab, 1, w * h, f);
100     h2 = h / 2;
101     w2 = w / 2;
102     cb = cb_tab;
103     cr = cr_tab;
104     for(i=0;i<h2;i++) {
105         fwrite(cb, 1, w2, f);
106         fwrite(cr, 1, w2, f);
107         cb += w2;
108         cr += w2;
109     }
110     fclose(f);
111
112     free(lum_tab);
113     free(cb_tab);
114     free(cr_tab);
115 }
116
117 unsigned char *rgb_tab;
118 int width, height, wrap;
119
120 void put_pixel(int x, int y, int r, int g, int b)
121 {
122     unsigned char *p;
123
124     if (x < 0 || x >= width ||
125         y < 0 || y >= height)
126         return;
127
128     p = rgb_tab + y * wrap + x * 3;
129     p[0] = r;
130     p[1] = g;
131     p[2] = b;
132 }
133
134 unsigned char tab_r[256*256];
135 unsigned char tab_g[256*256];
136 unsigned char tab_b[256*256];
137
138 int teta = 0;
139 int h_cos [360];
140 int h_sin [360];
141
142 void gen_image(int num, int w, int h)
143 {
144   const int c = h_cos [teta];
145   const int s = h_sin [teta];
146   
147   const int xi = -(w/2) * c;
148   const int yi =  (w/2) * s;
149   
150   const int xj = -(h/2) * s;
151   const int yj = -(h/2) * c;
152   
153   unsigned dep;
154   int i,j;
155   
156   int x,y;
157   int xprime = xj;
158   int yprime = yj;
159
160
161   for (j=0;j<h;j++) {
162
163     x = xprime + xi;
164     xprime += s;
165
166     y = yprime + yi;
167     yprime += c;
168       
169     for ( i=0 ; i<w ; i++ ) {
170       x += c;
171       y -= s;
172       dep = ((x>>8)&255) + (y&(255<<8));
173       put_pixel(i, j, tab_r[dep], tab_g[dep], tab_b[dep]);
174     }
175   }
176   teta = (teta+1) % 360;
177 }
178
179 void init_demo() {
180   int i,j;
181   double h;
182   double radian;
183   char line[3 * 128];
184
185   FILE *fichier;
186
187
188   fichier = fopen("rotozoom-ffmpeg.pnm","r");
189   fread(line, 1, 15, fichier);
190   for (i=0;i<128;i++) {
191     fread(line,1,3*128,fichier);
192     for (j=0;j<128;j++) {
193           tab_r[256*i+j] = line[3*j    ];
194           tab_g[256*i+j] = line[3*j + 1];
195           tab_b[256*i+j] = line[3*j + 2];
196     }
197         memcpy(tab_r + 257*128 + i*256, tab_r + i*256, 128);
198         memcpy(tab_g + 257*128 + i*256, tab_g + i*256, 128);
199         memcpy(tab_b + 257*128 + i*256, tab_b + i*256, 128);
200   }
201   fclose(fichier);
202
203   fichier = fopen("rotozoom-tux.pnm","r");
204   fread(line, 1, 15, fichier);
205   for (i=0;i<128;i++) {
206     fread(line,1,3*128,fichier);
207     for (j=0;j<128;j++) {
208           tab_r[128 + 256*i+j] = line[3*j    ];
209           tab_g[128 + 256*i+j] = line[3*j + 1];
210           tab_b[128 + 256*i+j] = line[3*j + 2];
211     }
212         memcpy(tab_r + 256*128 + i*256, tab_r + 128 + i*256, 128);
213         memcpy(tab_g + 256*128 + i*256, tab_g + 128 + i*256, 128);
214         memcpy(tab_b + 256*128 + i*256, tab_b + 128 + i*256, 128);
215   }
216   fclose(fichier);
217
218
219
220   /* tables sin/cos */
221   for (i=0;i<360;i++) {
222     radian = 2*i*M_PI/360;
223     h = 2 + cos (radian);      
224     h_cos[i] = 256 * ( h * cos (radian) );
225     h_sin[i] = 256 * ( h * sin (radian) );
226   }
227 }
228
229 int main(int argc, char **argv)
230 {
231     int w, h, i;
232     char buf[1024];
233
234     if (argc != 2) {
235         printf("usage: %s directory/\n"
236                "generate a test video stream\n", argv[0]);
237         exit(1);
238     }
239
240     w = DEFAULT_WIDTH;
241     h = DEFAULT_HEIGHT;
242
243     rgb_tab = malloc(w * h * 3);
244     wrap = w * 3;
245     width = w;
246     height = h;
247
248     init_demo();
249
250     for(i=0;i<DEFAULT_NB_PICT;i++) {
251         snprintf(buf, sizeof(buf), "%s%03d.pgm", argv[1], i);
252         gen_image(i, w, h);
253         pgmyuv_save(buf, w, h, rgb_tab);
254     }
255     
256     free(rgb_tab);
257     return 0;
258 }