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