ffmpeg / tests / rotozoom.c @ e9c10459
History | View | Annotate | Download (7.4 KB)
1 |
/*
|
---|---|
2 |
* Generates a synthetic YUV video sequence suitable for codec testing.
|
3 |
*
|
4 |
* copyright (c) Sebastien Bechet <s.bechet@av7.net>
|
5 |
*
|
6 |
* This file is part of Libav.
|
7 |
*
|
8 |
* Libav is free software; you can redistribute it and/or
|
9 |
* modify it under the terms of the GNU Lesser General Public
|
10 |
* License as published by the Free Software Foundation; either
|
11 |
* version 2.1 of the License, or (at your option) any later version.
|
12 |
*
|
13 |
* Libav 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 GNU
|
16 |
* Lesser General Public License for more details.
|
17 |
*
|
18 |
* You should have received a copy of the GNU Lesser General Public
|
19 |
* License along with Libav; if not, write to the Free Software
|
20 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
21 |
*/
|
22 |
|
23 |
#include <stdlib.h> |
24 |
#include <stdio.h> |
25 |
#include <inttypes.h> |
26 |
|
27 |
#define FIXP (1 << 16) |
28 |
#define MY_PI 205887 //(M_PI * FIX) |
29 |
|
30 |
static int64_t int_pow(int64_t a, int p) |
31 |
{ |
32 |
int64_t v = FIXP; |
33 |
|
34 |
for (; p; p--) {
|
35 |
v *= a; |
36 |
v /= FIXP; |
37 |
} |
38 |
|
39 |
return v;
|
40 |
} |
41 |
|
42 |
static int64_t int_sin(int64_t a)
|
43 |
{ |
44 |
if (a < 0) |
45 |
a = MY_PI - a; // 0..inf
|
46 |
a %= 2 * MY_PI; // 0..2PI |
47 |
|
48 |
if (a >= MY_PI * 3 / 2) |
49 |
a -= 2 * MY_PI; // -PI / 2 .. 3PI / 2 |
50 |
if (a >= MY_PI /2) |
51 |
a = MY_PI - a; // -PI / 2 .. PI / 2
|
52 |
|
53 |
return a - int_pow(a, 3) / 6 + int_pow(a, 5) / 120 - int_pow(a, 7) / 5040; |
54 |
} |
55 |
|
56 |
#define SCALEBITS 8 |
57 |
#define ONE_HALF (1 << (SCALEBITS - 1)) |
58 |
#define FIX(x) ((int) ((x) * (1L << SCALEBITS) + 0.5)) |
59 |
typedef unsigned char UINT8; |
60 |
|
61 |
static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr, |
62 |
UINT8 *src, int width, int height) |
63 |
{ |
64 |
int wrap, wrap3, x, y;
|
65 |
int r, g, b, r1, g1, b1;
|
66 |
UINT8 *p; |
67 |
|
68 |
wrap = width; |
69 |
wrap3 = width * 3;
|
70 |
p = src; |
71 |
for (y = 0; y < height; y += 2) { |
72 |
for (x = 0; x < width; x += 2) { |
73 |
r = p[0];
|
74 |
g = p[1];
|
75 |
b = p[2];
|
76 |
r1 = r; |
77 |
g1 = g; |
78 |
b1 = b; |
79 |
lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + |
80 |
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; |
81 |
r = p[3];
|
82 |
g = p[4];
|
83 |
b = p[5];
|
84 |
r1 += r; |
85 |
g1 += g; |
86 |
b1 += b; |
87 |
lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + |
88 |
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; |
89 |
p += wrap3; |
90 |
lum += wrap; |
91 |
|
92 |
r = p[0];
|
93 |
g = p[1];
|
94 |
b = p[2];
|
95 |
r1 += r; |
96 |
g1 += g; |
97 |
b1 += b; |
98 |
lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + |
99 |
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; |
100 |
r = p[3];
|
101 |
g = p[4];
|
102 |
b = p[5];
|
103 |
r1 += r; |
104 |
g1 += g; |
105 |
b1 += b; |
106 |
lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + |
107 |
FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; |
108 |
|
109 |
cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + |
110 |
FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; |
111 |
cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - |
112 |
FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; |
113 |
|
114 |
cb++; |
115 |
cr++; |
116 |
p += -wrap3 + 2 * 3; |
117 |
lum += -wrap + 2;
|
118 |
} |
119 |
p += wrap3; |
120 |
lum += wrap; |
121 |
} |
122 |
} |
123 |
|
124 |
/* cif format */
|
125 |
#define DEFAULT_WIDTH 352 |
126 |
#define DEFAULT_HEIGHT 288 |
127 |
#define DEFAULT_NB_PICT 50 |
128 |
|
129 |
static void pgmyuv_save(const char *filename, int w, int h, |
130 |
unsigned char *rgb_tab) |
131 |
{ |
132 |
FILE *f; |
133 |
int i, h2, w2;
|
134 |
unsigned char *cb, *cr; |
135 |
unsigned char *lum_tab, *cb_tab, *cr_tab; |
136 |
|
137 |
lum_tab = malloc(w * h); |
138 |
cb_tab = malloc(w * h / 4);
|
139 |
cr_tab = malloc(w * h / 4);
|
140 |
|
141 |
rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h); |
142 |
|
143 |
f = fopen(filename, "wb");
|
144 |
fprintf(f, "P5\n%d %d\n%d\n", w, h * 3 / 2, 255); |
145 |
fwrite(lum_tab, 1, w * h, f);
|
146 |
h2 = h / 2;
|
147 |
w2 = w / 2;
|
148 |
cb = cb_tab; |
149 |
cr = cr_tab; |
150 |
for (i = 0; i < h2; i++) { |
151 |
fwrite(cb, 1, w2, f);
|
152 |
fwrite(cr, 1, w2, f);
|
153 |
cb += w2; |
154 |
cr += w2; |
155 |
} |
156 |
fclose(f); |
157 |
|
158 |
free(lum_tab); |
159 |
free(cb_tab); |
160 |
free(cr_tab); |
161 |
} |
162 |
|
163 |
unsigned char *rgb_tab; |
164 |
int width, height, wrap;
|
165 |
|
166 |
static void put_pixel(int x, int y, int r, int g, int b) |
167 |
{ |
168 |
unsigned char *p; |
169 |
|
170 |
if (x < 0 || x >= width || |
171 |
y < 0 || y >= height)
|
172 |
return;
|
173 |
|
174 |
p = rgb_tab + y * wrap + x * 3;
|
175 |
p[0] = r;
|
176 |
p[1] = g;
|
177 |
p[2] = b;
|
178 |
} |
179 |
|
180 |
unsigned char tab_r[256 * 256]; |
181 |
unsigned char tab_g[256 * 256]; |
182 |
unsigned char tab_b[256 * 256]; |
183 |
|
184 |
int h_cos [360]; |
185 |
int h_sin [360]; |
186 |
|
187 |
static int ipol(uint8_t *src, int x, int y) |
188 |
{ |
189 |
int int_x = x >> 16; |
190 |
int int_y = y >> 16; |
191 |
int frac_x = x & 0xFFFF; |
192 |
int frac_y = y & 0xFFFF; |
193 |
int s00 = src[( int_x & 255) + 256 * ( int_y & 255)]; |
194 |
int s01 = src[((int_x + 1) & 255) + 256 * ( int_y & 255)]; |
195 |
int s10 = src[( int_x & 255) + 256 * ((int_y + 1) & 255)]; |
196 |
int s11 = src[((int_x + 1) & 255) + 256 * ((int_y + 1) & 255)]; |
197 |
int s0 = (((1 << 16) - frac_x) * s00 + frac_x * s01) >> 8; |
198 |
int s1 = (((1 << 16) - frac_x) * s10 + frac_x * s11) >> 8; |
199 |
|
200 |
return (((1 << 16) - frac_y) * s0 + frac_y * s1) >> 24; |
201 |
} |
202 |
|
203 |
static void gen_image(int num, int w, int h) |
204 |
{ |
205 |
const int c = h_cos [num % 360]; |
206 |
const int s = h_sin [num % 360]; |
207 |
|
208 |
const int xi = -(w / 2) * c; |
209 |
const int yi = (w / 2) * s; |
210 |
|
211 |
const int xj = -(h / 2) * s; |
212 |
const int yj = -(h / 2) * c; |
213 |
int i, j;
|
214 |
|
215 |
int x, y;
|
216 |
int xprime = xj;
|
217 |
int yprime = yj;
|
218 |
|
219 |
for (j = 0; j < h; j++) { |
220 |
x = xprime + xi + FIXP * w / 2;
|
221 |
xprime += s; |
222 |
|
223 |
y = yprime + yi + FIXP * h / 2;
|
224 |
yprime += c; |
225 |
|
226 |
for (i = 0; i < w; i++ ) { |
227 |
x += c; |
228 |
y -= s; |
229 |
put_pixel(i, j, ipol(tab_r, x, y), ipol(tab_g, x, y), ipol(tab_b, x, y)); |
230 |
} |
231 |
} |
232 |
} |
233 |
|
234 |
#define W 256 |
235 |
#define H 256 |
236 |
|
237 |
static void init_demo(const char *filename) |
238 |
{ |
239 |
int i, j;
|
240 |
int h;
|
241 |
int radian;
|
242 |
char line[3 * W]; |
243 |
|
244 |
FILE *fichier; |
245 |
|
246 |
fichier = fopen(filename, "rb");
|
247 |
if (!fichier) {
|
248 |
perror(filename); |
249 |
exit(1);
|
250 |
} |
251 |
|
252 |
fread(line, 1, 15, fichier); |
253 |
for (i = 0; i < H; i++) { |
254 |
fread(line, 1, 3 * W, fichier); |
255 |
for (j = 0; j < W; j++) { |
256 |
tab_r[W * i + j] = line[3 * j ];
|
257 |
tab_g[W * i + j] = line[3 * j + 1]; |
258 |
tab_b[W * i + j] = line[3 * j + 2]; |
259 |
} |
260 |
} |
261 |
fclose(fichier); |
262 |
|
263 |
/* tables sin/cos */
|
264 |
for (i = 0; i < 360; i++) { |
265 |
radian = 2 * i * MY_PI / 360; |
266 |
h = 2 * FIXP + int_sin (radian);
|
267 |
h_cos[i] = h * int_sin(radian + MY_PI / 2) / 2 / FIXP; |
268 |
h_sin[i] = h * int_sin(radian) / 2 / FIXP;
|
269 |
} |
270 |
} |
271 |
|
272 |
int main(int argc, char **argv) |
273 |
{ |
274 |
int w, h, i;
|
275 |
char buf[1024]; |
276 |
|
277 |
if (argc != 3) { |
278 |
printf("usage: %s directory/ image.pnm\n"
|
279 |
"generate a test video stream\n", argv[0]); |
280 |
exit(1);
|
281 |
} |
282 |
|
283 |
w = DEFAULT_WIDTH; |
284 |
h = DEFAULT_HEIGHT; |
285 |
|
286 |
rgb_tab = malloc(w * h * 3);
|
287 |
wrap = w * 3;
|
288 |
width = w; |
289 |
height = h; |
290 |
|
291 |
init_demo(argv[2]);
|
292 |
|
293 |
for (i = 0; i < DEFAULT_NB_PICT; i++) { |
294 |
snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i); |
295 |
gen_image(i, w, h); |
296 |
pgmyuv_save(buf, w, h, rgb_tab); |
297 |
} |
298 |
|
299 |
free(rgb_tab); |
300 |
return 0; |
301 |
} |