alternative test video generator by (Sebastien Bechet <s dot bechet at av7 dot net>)
[libav.git] / tests / rotozoom.c
CommitLineData
66961636
MN
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))
13typedef unsigned char UINT8;
14
15static 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
83void 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
117unsigned char *rgb_tab;
118int width, height, wrap;
119
120void 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
134unsigned char tab_r[256*256];
135unsigned char tab_g[256*256];
136unsigned char tab_b[256*256];
137
138int teta = 0;
139int h_cos [360];
140int h_sin [360];
141
142void 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
179void 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
229int 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}