Home | History | Annotate | Download | only in test
      1 
      2 /* Bring up a window and play with it */
      3 
      4 #include <stdlib.h>
      5 #include <stdio.h>
      6 #include <string.h>
      7 
      8 #define BENCHMARK_SDL
      9 
     10 #define NOTICE(X)	printf("%s", X);
     11 
     12 #define WINDOW_WIDTH  640
     13 #define WINDOW_HEIGHT 480
     14 
     15 #include "SDL.h"
     16 
     17 SDL_Surface *screen, *pic;
     18 SDL_Overlay *overlay;
     19 int scale;
     20 int monochrome;
     21 int luminance;
     22 int w, h;
     23 
     24 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
     25 static void quit(int rc)
     26 {
     27 	SDL_Quit();
     28 	exit(rc);
     29 }
     30 
     31 /* NOTE: These RGB conversion functions are not intended for speed,
     32          only as examples.
     33 */
     34 
     35 void RGBtoYUV(Uint8 *rgb, int *yuv, int monochrome, int luminance)
     36 {
     37     if (monochrome)
     38     {
     39 #if 1 /* these are the two formulas that I found on the FourCC site... */
     40         yuv[0] = 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
     41         yuv[1] = 128;
     42         yuv[2] = 128;
     43 #else
     44         yuv[0] = (0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16;
     45         yuv[1] = 128;
     46         yuv[2] = 128;
     47 #endif
     48     }
     49     else
     50     {
     51 #if 1 /* these are the two formulas that I found on the FourCC site... */
     52         yuv[0] = 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
     53         yuv[1] = (rgb[2]-yuv[0])*0.565 + 128;
     54         yuv[2] = (rgb[0]-yuv[0])*0.713 + 128;
     55 #else
     56         yuv[0] = (0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16;
     57         yuv[1] = 128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2]);
     58         yuv[2] = 128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2]);
     59 #endif
     60     }
     61 
     62     if (luminance!=100)
     63     {
     64         yuv[0]=yuv[0]*luminance/100;
     65         if (yuv[0]>255)
     66             yuv[0]=255;
     67     }
     68 
     69     /* clamp values...if you need to, we don't seem to have a need */
     70     /*
     71     for(i=0;i<3;i++)
     72     {
     73         if(yuv[i]<0)
     74             yuv[i]=0;
     75         if(yuv[i]>255)
     76             yuv[i]=255;
     77     }
     78     */
     79 }
     80 
     81 void ConvertRGBtoYV12(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
     82 {
     83 	int x,y;
     84 	int yuv[3];
     85 	Uint8 *p,*op[3];
     86 
     87 	SDL_LockSurface(s);
     88 	SDL_LockYUVOverlay(o);
     89 
     90 	/* Black initialization */
     91 	/*
     92 	memset(o->pixels[0],0,o->pitches[0]*o->h);
     93 	memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
     94 	memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
     95 	*/
     96 
     97 	/* Convert */
     98 	for(y=0; y<s->h && y<o->h; y++)
     99 	{
    100 		p=((Uint8 *) s->pixels)+s->pitch*y;
    101 		op[0]=o->pixels[0]+o->pitches[0]*y;
    102 		op[1]=o->pixels[1]+o->pitches[1]*(y/2);
    103 		op[2]=o->pixels[2]+o->pitches[2]*(y/2);
    104 		for(x=0; x<s->w && x<o->w; x++)
    105 		{
    106 			RGBtoYUV(p, yuv, monochrome, luminance);
    107 			*(op[0]++)=yuv[0];
    108 			if(x%2==0 && y%2==0)
    109 			{
    110 				*(op[1]++)=yuv[2];
    111 				*(op[2]++)=yuv[1];
    112 			}
    113 			p+=s->format->BytesPerPixel;
    114 		}
    115 	}
    116 
    117 	SDL_UnlockYUVOverlay(o);
    118 	SDL_UnlockSurface(s);
    119 }
    120 
    121 void ConvertRGBtoIYUV(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
    122 {
    123 	int x,y;
    124 	int yuv[3];
    125 	Uint8 *p,*op[3];
    126 
    127 	SDL_LockSurface(s);
    128 	SDL_LockYUVOverlay(o);
    129 
    130 	/* Black initialization */
    131 	/*
    132 	memset(o->pixels[0],0,o->pitches[0]*o->h);
    133 	memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
    134 	memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
    135 	*/
    136 
    137 	/* Convert */
    138 	for(y=0; y<s->h && y<o->h; y++)
    139 	{
    140 		p=((Uint8 *) s->pixels)+s->pitch*y;
    141 		op[0]=o->pixels[0]+o->pitches[0]*y;
    142 		op[1]=o->pixels[1]+o->pitches[1]*(y/2);
    143 		op[2]=o->pixels[2]+o->pitches[2]*(y/2);
    144 		for(x=0; x<s->w && x<o->w; x++)
    145 		{
    146 			RGBtoYUV(p,yuv, monochrome, luminance);
    147 			*(op[0]++)=yuv[0];
    148 			if(x%2==0 && y%2==0)
    149 			{
    150 				*(op[1]++)=yuv[1];
    151 				*(op[2]++)=yuv[2];
    152 			}
    153 			p+=s->format->BytesPerPixel;
    154 		}
    155 	}
    156 
    157 	SDL_UnlockYUVOverlay(o);
    158 	SDL_UnlockSurface(s);
    159 }
    160 
    161 void ConvertRGBtoUYVY(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
    162 {
    163 	int x,y;
    164 	int yuv[3];
    165 	Uint8 *p,*op;
    166 
    167 	SDL_LockSurface(s);
    168 	SDL_LockYUVOverlay(o);
    169 
    170 	for(y=0; y<s->h && y<o->h; y++)
    171 	{
    172 		p=((Uint8 *) s->pixels)+s->pitch*y;
    173 		op=o->pixels[0]+o->pitches[0]*y;
    174 		for(x=0; x<s->w && x<o->w; x++)
    175 		{
    176 			RGBtoYUV(p, yuv, monochrome, luminance);
    177 			if(x%2==0)
    178 			{
    179 				*(op++)=yuv[1];
    180 				*(op++)=yuv[0];
    181 				*(op++)=yuv[2];
    182 			}
    183 			else
    184 				*(op++)=yuv[0];
    185 
    186 			p+=s->format->BytesPerPixel;
    187 		}
    188 	}
    189 
    190 	SDL_UnlockYUVOverlay(o);
    191 	SDL_UnlockSurface(s);
    192 }
    193 
    194 void ConvertRGBtoYVYU(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
    195 {
    196 	int x,y;
    197 	int yuv[3];
    198 	Uint8 *p,*op;
    199 
    200 	SDL_LockSurface(s);
    201 	SDL_LockYUVOverlay(o);
    202 
    203 	for(y=0; y<s->h && y<o->h; y++)
    204 	{
    205 		p=((Uint8 *) s->pixels)+s->pitch*y;
    206 		op=o->pixels[0]+o->pitches[0]*y;
    207 		for(x=0; x<s->w && x<o->w; x++)
    208 		{
    209 			RGBtoYUV(p,yuv, monochrome, luminance);
    210 			if(x%2==0)
    211 			{
    212 				*(op++)=yuv[0];
    213 				*(op++)=yuv[2];
    214 				op[1]=yuv[1];
    215 			}
    216 			else
    217 			{
    218 				*op=yuv[0];
    219 				op+=2;
    220 			}
    221 
    222 			p+=s->format->BytesPerPixel;
    223 		}
    224 	}
    225 
    226 	SDL_UnlockYUVOverlay(o);
    227 	SDL_UnlockSurface(s);
    228 }
    229 
    230 void ConvertRGBtoYUY2(SDL_Surface *s, SDL_Overlay *o, int monochrome, int luminance)
    231 {
    232 	int x,y;
    233 	int yuv[3];
    234 	Uint8 *p,*op;
    235 
    236 	SDL_LockSurface(s);
    237 	SDL_LockYUVOverlay(o);
    238 
    239 	for(y=0; y<s->h && y<o->h; y++)
    240 	{
    241 		p=((Uint8 *) s->pixels)+s->pitch*y;
    242 		op=o->pixels[0]+o->pitches[0]*y;
    243 		for(x=0; x<s->w && x<o->w; x++)
    244 		{
    245 			RGBtoYUV(p,yuv, monochrome, luminance);
    246 			if(x%2==0)
    247 			{
    248 				*(op++)=yuv[0];
    249 				*(op++)=yuv[1];
    250 				op[1]=yuv[2];
    251 			}
    252 			else
    253 			{
    254 				*op=yuv[0];
    255 				op+=2;
    256 			}
    257 
    258 			p+=s->format->BytesPerPixel;
    259 		}
    260 	}
    261 
    262 	SDL_UnlockYUVOverlay(o);
    263 	SDL_UnlockSurface(s);
    264 }
    265 
    266 void Draw()
    267 {
    268 	SDL_Rect rect;
    269 	int i;
    270         int disp;
    271 
    272 	if(!scale)
    273 	{
    274 		rect.w=overlay->w;
    275 		rect.h=overlay->h;
    276 		for(i=0; i<h-rect.h && i<w-rect.w; i++)
    277 		{
    278 			rect.x=i;
    279 			rect.y=i;
    280 			SDL_DisplayYUVOverlay(overlay,&rect);
    281 		}
    282 	}
    283 	else
    284 	{
    285 		rect.w=overlay->w/2;
    286 		rect.h=overlay->h/2;
    287 		rect.x=(w-rect.w)/2;
    288 		rect.y=(h-rect.h)/2;
    289                 disp=rect.y-1;
    290 		for(i=0; i<disp; i++)
    291 		{
    292                         rect.w+=2;
    293                         rect.h+=2;
    294                         rect.x--;
    295                         rect.y--;
    296 			SDL_DisplayYUVOverlay(overlay,&rect);
    297 		}
    298 	}
    299 	printf("Displayed %d times.\n",i);
    300 }
    301 
    302 static void PrintUsage(char *argv0)
    303 {
    304 	fprintf(stderr, "Usage: %s [arg] [arg] [arg] ...\n", argv0);
    305 	fprintf(stderr, "Where 'arg' is one of:\n");
    306 	fprintf(stderr, "	-delay <seconds>\n");
    307 	fprintf(stderr, "	-width <pixels>\n");
    308 	fprintf(stderr, "	-height <pixels>\n");
    309 	fprintf(stderr, "	-bpp <bits>\n");
    310 	fprintf(stderr, "	-format <fmt> (one of the: YV12, IYUV, YUY2, UYVY, YVYU)\n");
    311 	fprintf(stderr, "	-hw\n");
    312 	fprintf(stderr, "	-flip\n");
    313 	fprintf(stderr, "	-scale (test scaling features, from 50%% upto window size)\n");
    314 	fprintf(stderr, "	-mono (use monochromatic RGB2YUV conversion)\n");
    315 	fprintf(stderr, "	-lum <perc> (use luminance correction during RGB2YUV conversion,\n");
    316 	fprintf(stderr, "	             from 0%% to unlimited, normal is 100%%)\n");
    317 	fprintf(stderr, "	-help (shows this help)\n");
    318 	fprintf(stderr, "	-fullscreen (test overlay in fullscreen mode)\n");
    319 }
    320 
    321 int main(int argc, char **argv)
    322 {
    323 	char *argv0 = argv[0];
    324 	int flip;
    325 	int delay;
    326 	int desired_bpp;
    327 	Uint32 video_flags, overlay_format;
    328 	char *bmpfile;
    329 #ifdef BENCHMARK_SDL
    330 	Uint32 then, now;
    331 #endif
    332 	int i;
    333 
    334 	/* Set default options and check command-line */
    335 	flip = 0;
    336 	scale=0;
    337         monochrome=0;
    338         luminance=100;
    339 	delay = 1;
    340 	w = WINDOW_WIDTH;
    341 	h = WINDOW_HEIGHT;
    342 	desired_bpp = 0;
    343 	video_flags = 0;
    344 	overlay_format = SDL_YV12_OVERLAY;
    345 
    346 	while ( argc > 1 ) {
    347 		if ( strcmp(argv[1], "-delay") == 0 ) {
    348 			if ( argv[2] ) {
    349 				delay = atoi(argv[2]);
    350 				argv += 2;
    351 				argc -= 2;
    352 			} else {
    353 				fprintf(stderr,
    354 				"The -delay option requires an argument\n");
    355 				return(1);
    356 			}
    357 		} else
    358 		if ( strcmp(argv[1], "-width") == 0 ) {
    359 			if ( argv[2] && ((w = atoi(argv[2])) > 0) ) {
    360 				argv += 2;
    361 				argc -= 2;
    362 			} else {
    363 				fprintf(stderr,
    364 				"The -width option requires an argument\n");
    365 				return(1);
    366 			}
    367 		} else
    368 		if ( strcmp(argv[1], "-height") == 0 ) {
    369 			if ( argv[2] && ((h = atoi(argv[2])) > 0) ) {
    370 				argv += 2;
    371 				argc -= 2;
    372 			} else {
    373 				fprintf(stderr,
    374 				"The -height option requires an argument\n");
    375 				return(1);
    376 			}
    377 		} else
    378 		if ( strcmp(argv[1], "-bpp") == 0 ) {
    379 			if ( argv[2] ) {
    380 				desired_bpp = atoi(argv[2]);
    381 				argv += 2;
    382 				argc -= 2;
    383 			} else {
    384 				fprintf(stderr,
    385 				"The -bpp option requires an argument\n");
    386 				return(1);
    387 			}
    388 		} else
    389 		if ( strcmp(argv[1], "-lum") == 0 ) {
    390 			if ( argv[2] ) {
    391 				luminance = atoi(argv[2]);
    392 				argv += 2;
    393 				argc -= 2;
    394 			} else {
    395 				fprintf(stderr,
    396 				"The -lum option requires an argument\n");
    397 				return(1);
    398 			}
    399 		} else
    400 		if ( strcmp(argv[1], "-format") == 0 ) {
    401 			if ( argv[2] ) {
    402 				if(!strcmp(argv[2],"YV12"))
    403 					overlay_format = SDL_YV12_OVERLAY;
    404 				else if(!strcmp(argv[2],"IYUV"))
    405 					overlay_format = SDL_IYUV_OVERLAY;
    406 				else if(!strcmp(argv[2],"YUY2"))
    407 					overlay_format = SDL_YUY2_OVERLAY;
    408 				else if(!strcmp(argv[2],"UYVY"))
    409 					overlay_format = SDL_UYVY_OVERLAY;
    410 				else if(!strcmp(argv[2],"YVYU"))
    411 					overlay_format = SDL_YVYU_OVERLAY;
    412 				else
    413 				{
    414 					fprintf(stderr, "The -format option %s is not recognized\n",argv[2]);
    415 					return(1);
    416 				}
    417 				argv += 2;
    418 				argc -= 2;
    419 			} else {
    420 				fprintf(stderr,
    421 				"The -format option requires an argument\n");
    422 				return(1);
    423 			}
    424 		} else
    425 		if ( strcmp(argv[1], "-hw") == 0 ) {
    426 			video_flags |= SDL_HWSURFACE;
    427 			argv += 1;
    428 			argc -= 1;
    429 		} else
    430 		if ( strcmp(argv[1], "-flip") == 0 ) {
    431 			video_flags |= SDL_DOUBLEBUF;
    432 			argv += 1;
    433 			argc -= 1;
    434 		} else
    435 		if ( strcmp(argv[1], "-scale") == 0 ) {
    436 			scale = 1;
    437 			argv += 1;
    438 			argc -= 1;
    439 		} else
    440 		if ( strcmp(argv[1], "-mono") == 0 ) {
    441 			monochrome = 1;
    442 			argv += 1;
    443 			argc -= 1;
    444 		} else
    445 		if (( strcmp(argv[1], "-help") == 0 ) || (strcmp(argv[1], "-h") == 0)) {
    446                         PrintUsage(argv0);
    447                         return(1);
    448 		} else
    449 		if ( strcmp(argv[1], "-fullscreen") == 0 ) {
    450 			video_flags |= SDL_FULLSCREEN;
    451 			argv += 1;
    452 			argc -= 1;
    453 		} else
    454 			break;
    455 	}
    456 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
    457 		fprintf(stderr,
    458 			"Couldn't initialize SDL: %s\n", SDL_GetError());
    459 		return(1);
    460 	}
    461 
    462 	/* Initialize the display */
    463 	screen = SDL_SetVideoMode(w, h, desired_bpp, video_flags);
    464 	if ( screen == NULL ) {
    465 		fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
    466 					w, h, desired_bpp, SDL_GetError());
    467 		quit(1);
    468 	}
    469 	printf("Set%s %dx%dx%d mode\n",
    470 			screen->flags & SDL_FULLSCREEN ? " fullscreen" : "",
    471 			screen->w, screen->h, screen->format->BitsPerPixel);
    472 	printf("(video surface located in %s memory)\n",
    473 			(screen->flags&SDL_HWSURFACE) ? "video" : "system");
    474 	if ( screen->flags & SDL_DOUBLEBUF ) {
    475 		printf("Double-buffering enabled\n");
    476 		flip = 1;
    477 	}
    478 
    479 	/* Set the window manager title bar */
    480 	SDL_WM_SetCaption("SDL test overlay", "testoverlay");
    481 
    482 	/* Load picture */
    483 	bmpfile=(argv[1]?argv[1]:"sample.bmp");
    484 	pic = SDL_LoadBMP(bmpfile);
    485 	if ( pic == NULL ) {
    486 		fprintf(stderr, "Couldn't load %s: %s\n", bmpfile,
    487 							SDL_GetError());
    488 		quit(1);
    489 	}
    490 
    491 	/* Convert the picture to 32bits, for easy conversion */
    492 	{
    493 		SDL_Surface *newsurf;
    494 		SDL_PixelFormat format;
    495 
    496 		format.palette=NULL;
    497 		format.BitsPerPixel=32;
    498 		format.BytesPerPixel=4;
    499 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    500 		format.Rshift=0;
    501 		format.Gshift=8;
    502 		format.Bshift=16;
    503 #else
    504 		format.Rshift=24;
    505 		format.Gshift=16;
    506 		format.Bshift=8;
    507 #endif
    508 		format.Ashift=0;
    509 		format.Rmask=0xff<<format.Rshift;
    510 		format.Gmask=0xff<<format.Gshift;
    511 		format.Bmask=0xff<<format.Bshift;
    512 		format.Amask=0;
    513 		format.Rloss=0;
    514 		format.Gloss=0;
    515 		format.Bloss=0;
    516 		format.Aloss=8;
    517 		format.colorkey=0;
    518 		format.alpha=0;
    519 
    520 		newsurf=SDL_ConvertSurface(pic, &format, SDL_SWSURFACE);
    521 		if(!newsurf)
    522 		{
    523 			fprintf(stderr, "Couldn't convert picture to 32bits RGB: %s\n",
    524 							SDL_GetError());
    525 			quit(1);
    526 		}
    527 		SDL_FreeSurface(pic);
    528 		pic=newsurf;
    529 	}
    530 
    531 	/* Create the overlay */
    532 	overlay = SDL_CreateYUVOverlay(pic->w, pic->h, overlay_format, screen);
    533 	if ( overlay == NULL ) {
    534 		fprintf(stderr, "Couldn't create overlay: %s\n", SDL_GetError());
    535 		quit(1);
    536 	}
    537 	printf("Created %dx%dx%d %s %s overlay\n",overlay->w,overlay->h,overlay->planes,
    538 			overlay->hw_overlay?"hardware":"software",
    539 			overlay->format==SDL_YV12_OVERLAY?"YV12":
    540 			overlay->format==SDL_IYUV_OVERLAY?"IYUV":
    541 			overlay->format==SDL_YUY2_OVERLAY?"YUY2":
    542 			overlay->format==SDL_UYVY_OVERLAY?"UYVY":
    543 			overlay->format==SDL_YVYU_OVERLAY?"YVYU":
    544 			"Unknown");
    545 	for(i=0; i<overlay->planes; i++)
    546 	{
    547 		printf("  plane %d: pitch=%d\n", i, overlay->pitches[i]);
    548 	}
    549 
    550 	/* Convert to YUV, and draw to the overlay */
    551 #ifdef BENCHMARK_SDL
    552 	then = SDL_GetTicks();
    553 #endif
    554 	switch(overlay->format)
    555 	{
    556 		case SDL_YV12_OVERLAY:
    557 			ConvertRGBtoYV12(pic,overlay,monochrome,luminance);
    558 			break;
    559 		case SDL_UYVY_OVERLAY:
    560 			ConvertRGBtoUYVY(pic,overlay,monochrome,luminance);
    561 			break;
    562 		case SDL_YVYU_OVERLAY:
    563 			ConvertRGBtoYVYU(pic,overlay,monochrome,luminance);
    564 			break;
    565 		case SDL_YUY2_OVERLAY:
    566 			ConvertRGBtoYUY2(pic,overlay,monochrome,luminance);
    567 			break;
    568 		case SDL_IYUV_OVERLAY:
    569 			ConvertRGBtoIYUV(pic,overlay,monochrome,luminance);
    570 			break;
    571 		default:
    572 			printf("cannot convert RGB picture to obtained YUV format!\n");
    573 			quit(1);
    574 			break;
    575 	}
    576 #ifdef BENCHMARK_SDL
    577 	now = SDL_GetTicks();
    578 	printf("Conversion Time: %d milliseconds\n", now-then);
    579 #endif
    580 
    581 	/* Do all the drawing work */
    582 #ifdef BENCHMARK_SDL
    583 	then = SDL_GetTicks();
    584 #endif
    585 	Draw();
    586 #ifdef BENCHMARK_SDL
    587 	now = SDL_GetTicks();
    588 	printf("Time: %d milliseconds\n", now-then);
    589 #endif
    590 	SDL_Delay(delay*1000);
    591 	SDL_Quit();
    592 	return(0);
    593 }
    594 
    595