SDL-1.2.14
[sdl_omap.git] / test / testoverlay.c
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