Libav
|
00001 /* 00002 * Generates a synthetic YUV video sequence suitable for codec testing. 00003 * 00004 * copyright (c) Sebastien Bechet <s.bechet@av7.net> 00005 * 00006 * This file is part of FFmpeg. 00007 * 00008 * FFmpeg is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * FFmpeg is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with FFmpeg; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #include <stdlib.h> 00024 #include <stdio.h> 00025 #include <inttypes.h> 00026 00027 #define FIXP (1<<16) 00028 #define MY_PI 205887 //(M_PI*FIX) 00029 00030 static int64_t int_pow(int64_t a, int p){ 00031 int64_t v= FIXP; 00032 00033 for(; p; p--){ 00034 v*= a; 00035 v/= FIXP; 00036 } 00037 00038 return v; 00039 } 00040 00041 static int64_t int_sin(int64_t a){ 00042 if(a<0) a= MY_PI-a; // 0..inf 00043 a %= 2*MY_PI; // 0..2PI 00044 00045 if(a>=MY_PI*3/2) a -= 2*MY_PI; // -PI/2 .. 3PI/2 00046 if(a>=MY_PI/2 ) a = MY_PI - a; // -PI/2 .. PI/2 00047 00048 return a - int_pow(a, 3)/6 + int_pow(a, 5)/120 - int_pow(a, 7)/5040; 00049 } 00050 00051 #define SCALEBITS 8 00052 #define ONE_HALF (1 << (SCALEBITS - 1)) 00053 #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5)) 00054 typedef unsigned char UINT8; 00055 00056 static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr, 00057 UINT8 *src, int width, int height) 00058 { 00059 int wrap, wrap3, x, y; 00060 int r, g, b, r1, g1, b1; 00061 UINT8 *p; 00062 00063 wrap = width; 00064 wrap3 = width * 3; 00065 p = src; 00066 for(y=0;y<height;y+=2) { 00067 for(x=0;x<width;x+=2) { 00068 r = p[0]; 00069 g = p[1]; 00070 b = p[2]; 00071 r1 = r; 00072 g1 = g; 00073 b1 = b; 00074 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 00075 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; 00076 r = p[3]; 00077 g = p[4]; 00078 b = p[5]; 00079 r1 += r; 00080 g1 += g; 00081 b1 += b; 00082 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 00083 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; 00084 p += wrap3; 00085 lum += wrap; 00086 00087 r = p[0]; 00088 g = p[1]; 00089 b = p[2]; 00090 r1 += r; 00091 g1 += g; 00092 b1 += b; 00093 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 00094 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; 00095 r = p[3]; 00096 g = p[4]; 00097 b = p[5]; 00098 r1 += r; 00099 g1 += g; 00100 b1 += b; 00101 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 00102 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; 00103 00104 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 00105 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; 00106 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 00107 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; 00108 00109 cb++; 00110 cr++; 00111 p += -wrap3 + 2 * 3; 00112 lum += -wrap + 2; 00113 } 00114 p += wrap3; 00115 lum += wrap; 00116 } 00117 } 00118 00119 /* cif format */ 00120 #define DEFAULT_WIDTH 352 00121 #define DEFAULT_HEIGHT 288 00122 #define DEFAULT_NB_PICT 50 00123 00124 static void pgmyuv_save(const char *filename, int w, int h, 00125 unsigned char *rgb_tab) 00126 { 00127 FILE *f; 00128 int i, h2, w2; 00129 unsigned char *cb, *cr; 00130 unsigned char *lum_tab, *cb_tab, *cr_tab; 00131 00132 lum_tab = malloc(w * h); 00133 cb_tab = malloc((w * h) / 4); 00134 cr_tab = malloc((w * h) / 4); 00135 00136 rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h); 00137 00138 f = fopen(filename,"wb"); 00139 fprintf(f, "P5\n%d %d\n%d\n", w, (h * 3) / 2, 255); 00140 fwrite(lum_tab, 1, w * h, f); 00141 h2 = h / 2; 00142 w2 = w / 2; 00143 cb = cb_tab; 00144 cr = cr_tab; 00145 for(i=0;i<h2;i++) { 00146 fwrite(cb, 1, w2, f); 00147 fwrite(cr, 1, w2, f); 00148 cb += w2; 00149 cr += w2; 00150 } 00151 fclose(f); 00152 00153 free(lum_tab); 00154 free(cb_tab); 00155 free(cr_tab); 00156 } 00157 00158 unsigned char *rgb_tab; 00159 int width, height, wrap; 00160 00161 static void put_pixel(int x, int y, int r, int g, int b) 00162 { 00163 unsigned char *p; 00164 00165 if (x < 0 || x >= width || 00166 y < 0 || y >= height) 00167 return; 00168 00169 p = rgb_tab + y * wrap + x * 3; 00170 p[0] = r; 00171 p[1] = g; 00172 p[2] = b; 00173 } 00174 00175 unsigned char tab_r[256*256]; 00176 unsigned char tab_g[256*256]; 00177 unsigned char tab_b[256*256]; 00178 00179 int h_cos [360]; 00180 int h_sin [360]; 00181 00182 static int ipol(uint8_t *src, int x, int y){ 00183 int int_x= x>>16; 00184 int int_y= y>>16; 00185 int frac_x= x&0xFFFF; 00186 int frac_y= y&0xFFFF; 00187 int s00= src[ ( int_x &255) + 256*( int_y &255) ]; 00188 int s01= src[ ((int_x+1)&255) + 256*( int_y &255) ]; 00189 int s10= src[ ( int_x &255) + 256*((int_y+1)&255) ]; 00190 int s11= src[ ((int_x+1)&255) + 256*((int_y+1)&255) ]; 00191 int s0= (((1<<16) - frac_x)*s00 + frac_x*s01)>>8; 00192 int s1= (((1<<16) - frac_x)*s10 + frac_x*s11)>>8; 00193 00194 return (((1<<16) - frac_y)*s0 + frac_y*s1)>>24; 00195 } 00196 00197 static void gen_image(int num, int w, int h) 00198 { 00199 const int c = h_cos [num % 360]; 00200 const int s = h_sin [num % 360]; 00201 00202 const int xi = -(w/2) * c; 00203 const int yi = (w/2) * s; 00204 00205 const int xj = -(h/2) * s; 00206 const int yj = -(h/2) * c; 00207 int i,j; 00208 00209 int x,y; 00210 int xprime = xj; 00211 int yprime = yj; 00212 00213 00214 for (j=0;j<h;j++) { 00215 00216 x = xprime + xi + FIXP*w/2; 00217 xprime += s; 00218 00219 y = yprime + yi + FIXP*h/2; 00220 yprime += c; 00221 00222 for ( i=0 ; i<w ; i++ ) { 00223 x += c; 00224 y -= s; 00225 #if 1 00226 put_pixel(i, j, ipol(tab_r, x, y), ipol(tab_g, x, y), ipol(tab_b, x, y)); 00227 #else 00228 { 00229 unsigned dep; 00230 dep = ((x>>16)&255) + (((y>>16)&255)<<8); 00231 put_pixel(i, j, tab_r[dep], tab_g[dep], tab_b[dep]); 00232 } 00233 #endif 00234 } 00235 } 00236 } 00237 00238 #define W 256 00239 #define H 256 00240 00241 static void init_demo(const char *filename) { 00242 int i,j; 00243 int h; 00244 int radian; 00245 char line[3 * W]; 00246 00247 FILE *fichier; 00248 00249 fichier = fopen(filename,"rb"); 00250 if (!fichier) { 00251 perror(filename); 00252 exit(1); 00253 } 00254 00255 fread(line, 1, 15, fichier); 00256 for (i=0;i<H;i++) { 00257 fread(line,1,3*W,fichier); 00258 for (j=0;j<W;j++) { 00259 tab_r[W*i+j] = line[3*j ]; 00260 tab_g[W*i+j] = line[3*j + 1]; 00261 tab_b[W*i+j] = line[3*j + 2]; 00262 } 00263 } 00264 fclose(fichier); 00265 00266 /* tables sin/cos */ 00267 for (i=0;i<360;i++) { 00268 radian = 2*i*MY_PI/360; 00269 h = 2*FIXP + int_sin (radian); 00270 h_cos[i] = ( h * int_sin (radian + MY_PI/2) )/2/FIXP; 00271 h_sin[i] = ( h * int_sin (radian ) )/2/FIXP; 00272 } 00273 } 00274 00275 int main(int argc, char **argv) 00276 { 00277 int w, h, i; 00278 char buf[1024]; 00279 00280 if (argc != 3) { 00281 printf("usage: %s directory/ image.pnm\n" 00282 "generate a test video stream\n", argv[0]); 00283 exit(1); 00284 } 00285 00286 w = DEFAULT_WIDTH; 00287 h = DEFAULT_HEIGHT; 00288 00289 rgb_tab = malloc(w * h * 3); 00290 wrap = w * 3; 00291 width = w; 00292 height = h; 00293 00294 init_demo(argv[2]); 00295 00296 for(i=0;i<DEFAULT_NB_PICT;i++) { 00297 snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i); 00298 gen_image(i, w, h); 00299 pgmyuv_save(buf, w, h, rgb_tab); 00300 } 00301 00302 free(rgb_tab); 00303 return 0; 00304 }