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 30static 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 41static 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)) 54typedef unsigned char UINT8; 55 56static 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 124static 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 158unsigned char *rgb_tab; 159int width, height, wrap; 160 161static 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 175unsigned char tab_r[256*256]; 176unsigned char tab_g[256*256]; 177unsigned char tab_b[256*256]; 178 179int teta = 0; 180int h_cos [360]; 181int h_sin [360]; 182 183static 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 198static 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 243static 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 277int 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} 307