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