test/testoverlay.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 17 May 2006 08:18:28 +0000
branchSDL-1.3
changeset 1659 14717b52abc0
parent 1439 4d3bb026cd16
child 1662 782fd950bd46
child 1895 c121d94672cb
permissions -rw-r--r--
Merge trunk-1.3-3
     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