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