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