1 /* 2 Copyright (C) 1997-2014 Sam Lantinga <slouken (at) libsdl.org> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11 */ 12 /******************************************************************************** 13 * * 14 * Test of the overlay used for moved pictures, test more closed to real life. * 15 * Running trojan moose :) Coded by Mike Gorchak. * 16 * * 17 ********************************************************************************/ 18 19 #include <stdlib.h> 20 #include <stdio.h> 21 #include <string.h> 22 23 #include "SDL.h" 24 25 #define MOOSEPIC_W 64 26 #define MOOSEPIC_H 88 27 28 #define MOOSEFRAME_SIZE (MOOSEPIC_W * MOOSEPIC_H) 29 #define MOOSEFRAMES_COUNT 10 30 31 SDL_Color MooseColors[84] = { 32 {49, 49, 49} 33 , {66, 24, 0} 34 , {66, 33, 0} 35 , {66, 66, 66} 36 , 37 {66, 115, 49} 38 , {74, 33, 0} 39 , {74, 41, 16} 40 , {82, 33, 8} 41 , 42 {82, 41, 8} 43 , {82, 49, 16} 44 , {82, 82, 82} 45 , {90, 41, 8} 46 , 47 {90, 41, 16} 48 , {90, 57, 24} 49 , {99, 49, 16} 50 , {99, 66, 24} 51 , 52 {99, 66, 33} 53 , {99, 74, 33} 54 , {107, 57, 24} 55 , {107, 82, 41} 56 , 57 {115, 57, 33} 58 , {115, 66, 33} 59 , {115, 66, 41} 60 , {115, 74, 0} 61 , 62 {115, 90, 49} 63 , {115, 115, 115} 64 , {123, 82, 0} 65 , {123, 99, 57} 66 , 67 {132, 66, 41} 68 , {132, 74, 41} 69 , {132, 90, 8} 70 , {132, 99, 33} 71 , 72 {132, 99, 66} 73 , {132, 107, 66} 74 , {140, 74, 49} 75 , {140, 99, 16} 76 , 77 {140, 107, 74} 78 , {140, 115, 74} 79 , {148, 107, 24} 80 , {148, 115, 82} 81 , 82 {148, 123, 74} 83 , {148, 123, 90} 84 , {156, 115, 33} 85 , {156, 115, 90} 86 , 87 {156, 123, 82} 88 , {156, 132, 82} 89 , {156, 132, 99} 90 , {156, 156, 156} 91 , 92 {165, 123, 49} 93 , {165, 123, 90} 94 , {165, 132, 82} 95 , {165, 132, 90} 96 , 97 {165, 132, 99} 98 , {165, 140, 90} 99 , {173, 132, 57} 100 , {173, 132, 99} 101 , 102 {173, 140, 107} 103 , {173, 140, 115} 104 , {173, 148, 99} 105 , {173, 173, 173} 106 , 107 {181, 140, 74} 108 , {181, 148, 115} 109 , {181, 148, 123} 110 , {181, 156, 107} 111 , 112 {189, 148, 123} 113 , {189, 156, 82} 114 , {189, 156, 123} 115 , {189, 156, 132} 116 , 117 {189, 189, 189} 118 , {198, 156, 123} 119 , {198, 165, 132} 120 , {206, 165, 99} 121 , 122 {206, 165, 132} 123 , {206, 173, 140} 124 , {206, 206, 206} 125 , {214, 173, 115} 126 , 127 {214, 173, 140} 128 , {222, 181, 148} 129 , {222, 189, 132} 130 , {222, 189, 156} 131 , 132 {222, 222, 222} 133 , {231, 198, 165} 134 , {231, 231, 231} 135 , {239, 206, 173} 136 }; 137 138 139 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ 140 static void 141 quit(int rc) 142 { 143 SDL_Quit(); 144 exit(rc); 145 } 146 147 /* All RGB2YUV conversion code and some other parts of code has been taken from testoverlay.c */ 148 149 /* NOTE: These RGB conversion functions are not intended for speed, 150 only as examples. 151 */ 152 153 void 154 RGBtoYUV(Uint8 * rgb, int *yuv, int monochrome, int luminance) 155 { 156 if (monochrome) { 157 #if 1 /* these are the two formulas that I found on the FourCC site... */ 158 yuv[0] = (int)(0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]); 159 yuv[1] = 128; 160 yuv[2] = 128; 161 #else 162 yuv[0] = (int)(0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16; 163 yuv[1] = 128; 164 yuv[2] = 128; 165 #endif 166 } else { 167 #if 1 /* these are the two formulas that I found on the FourCC site... */ 168 yuv[0] = (int)(0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]); 169 yuv[1] = (int)((rgb[2] - yuv[0]) * 0.565 + 128); 170 yuv[2] = (int)((rgb[0] - yuv[0]) * 0.713 + 128); 171 #else 172 yuv[0] = (0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16; 173 yuv[1] = 128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2]); 174 yuv[2] = 128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2]); 175 #endif 176 } 177 178 if (luminance != 100) { 179 yuv[0] = yuv[0] * luminance / 100; 180 if (yuv[0] > 255) 181 yuv[0] = 255; 182 } 183 } 184 185 void 186 ConvertRGBtoYV12(Uint8 *rgb, Uint8 *out, int w, int h, 187 int monochrome, int luminance) 188 { 189 int x, y; 190 int yuv[3]; 191 Uint8 *op[3]; 192 193 op[0] = out; 194 op[1] = op[0] + w*h; 195 op[2] = op[1] + w*h/4; 196 for (y = 0; y < h; ++y) { 197 for (x = 0; x < w; ++x) { 198 RGBtoYUV(rgb, yuv, monochrome, luminance); 199 *(op[0]++) = yuv[0]; 200 if (x % 2 == 0 && y % 2 == 0) { 201 *(op[1]++) = yuv[2]; 202 *(op[2]++) = yuv[1]; 203 } 204 rgb += 3; 205 } 206 } 207 } 208 209 static void 210 PrintUsage(char *argv0) 211 { 212 SDL_Log("Usage: %s [arg] [arg] [arg] ...\n", argv0); 213 SDL_Log("\n"); 214 SDL_Log("Where 'arg' is any of the following options:\n"); 215 SDL_Log("\n"); 216 SDL_Log(" -fps <frames per second>\n"); 217 SDL_Log(" -nodelay\n"); 218 SDL_Log(" -format <fmt> (one of the: YV12, IYUV, YUY2, UYVY, YVYU)\n"); 219 SDL_Log(" -scale <scale factor> (initial scale of the overlay)\n"); 220 SDL_Log(" -help (shows this help)\n"); 221 SDL_Log("\n"); 222 SDL_Log("Press ESC to exit, or SPACE to freeze the movie while application running.\n"); 223 SDL_Log("\n"); 224 } 225 226 int 227 main(int argc, char **argv) 228 { 229 Uint8 *RawMooseData; 230 SDL_RWops *handle; 231 int window_w; 232 int window_h; 233 SDL_Window *window; 234 SDL_Renderer *renderer; 235 Uint8 MooseFrame[MOOSEFRAMES_COUNT][MOOSEFRAME_SIZE*2]; 236 SDL_Texture *MooseTexture; 237 SDL_Rect displayrect; 238 SDL_Event event; 239 int paused = 0; 240 int i, j; 241 int fps = 12; 242 int fpsdelay; 243 int nodelay = 0; 244 Uint32 pixel_format = SDL_PIXELFORMAT_YV12; 245 int scale = 5; 246 SDL_bool done = SDL_FALSE; 247 248 /* Enable standard application logging */ 249 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 250 251 if (SDL_Init(SDL_INIT_VIDEO) < 0) { 252 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); 253 return 3; 254 } 255 256 while (argc > 1) { 257 if (strcmp(argv[1], "-fps") == 0) { 258 if (argv[2]) { 259 fps = atoi(argv[2]); 260 if (fps == 0) { 261 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 262 "The -fps option requires an argument [from 1 to 1000], default is 12.\n"); 263 quit(10); 264 } 265 if ((fps < 0) || (fps > 1000)) { 266 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 267 "The -fps option must be in range from 1 to 1000, default is 12.\n"); 268 quit(10); 269 } 270 argv += 2; 271 argc -= 2; 272 } else { 273 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 274 "The -fps option requires an argument [from 1 to 1000], default is 12.\n"); 275 quit(10); 276 } 277 } else if (strcmp(argv[1], "-nodelay") == 0) { 278 nodelay = 1; 279 argv += 1; 280 argc -= 1; 281 } else if (strcmp(argv[1], "-scale") == 0) { 282 if (argv[2]) { 283 scale = atoi(argv[2]); 284 if (scale == 0) { 285 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 286 "The -scale option requires an argument [from 1 to 50], default is 5.\n"); 287 quit(10); 288 } 289 if ((scale < 0) || (scale > 50)) { 290 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 291 "The -scale option must be in range from 1 to 50, default is 5.\n"); 292 quit(10); 293 } 294 argv += 2; 295 argc -= 2; 296 } else { 297 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 298 "The -fps option requires an argument [from 1 to 1000], default is 12.\n"); 299 quit(10); 300 } 301 } else if ((strcmp(argv[1], "-help") == 0) 302 || (strcmp(argv[1], "-h") == 0)) { 303 PrintUsage(argv[0]); 304 quit(0); 305 } else { 306 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized option: %s.\n", argv[1]); 307 quit(10); 308 } 309 break; 310 } 311 312 RawMooseData = (Uint8 *) malloc(MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT); 313 if (RawMooseData == NULL) { 314 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't allocate memory for movie !\n"); 315 free(RawMooseData); 316 quit(1); 317 } 318 319 /* load the trojan moose images */ 320 handle = SDL_RWFromFile("moose.dat", "rb"); 321 if (handle == NULL) { 322 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n"); 323 free(RawMooseData); 324 quit(2); 325 } 326 327 SDL_RWread(handle, RawMooseData, MOOSEFRAME_SIZE, MOOSEFRAMES_COUNT); 328 329 SDL_RWclose(handle); 330 331 /* Create the window and renderer */ 332 window_w = MOOSEPIC_W * scale; 333 window_h = MOOSEPIC_H * scale; 334 window = SDL_CreateWindow("Happy Moose", 335 SDL_WINDOWPOS_UNDEFINED, 336 SDL_WINDOWPOS_UNDEFINED, 337 window_w, window_h, 338 SDL_WINDOW_RESIZABLE); 339 if (!window) { 340 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError()); 341 free(RawMooseData); 342 quit(4); 343 } 344 345 renderer = SDL_CreateRenderer(window, -1, 0); 346 if (!renderer) { 347 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError()); 348 free(RawMooseData); 349 quit(4); 350 } 351 352 MooseTexture = SDL_CreateTexture(renderer, pixel_format, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H); 353 if (!MooseTexture) { 354 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError()); 355 free(RawMooseData); 356 quit(5); 357 } 358 /* Uncomment this to check vertex color with a YUV texture */ 359 /* SDL_SetTextureColorMod(MooseTexture, 0xff, 0x80, 0x80); */ 360 361 for (i = 0; i < MOOSEFRAMES_COUNT; i++) { 362 Uint8 MooseFrameRGB[MOOSEFRAME_SIZE*3]; 363 Uint8 *rgb; 364 Uint8 *frame; 365 366 rgb = MooseFrameRGB; 367 frame = RawMooseData + i * MOOSEFRAME_SIZE; 368 for (j = 0; j < MOOSEFRAME_SIZE; ++j) { 369 rgb[0] = MooseColors[frame[j]].r; 370 rgb[1] = MooseColors[frame[j]].g; 371 rgb[2] = MooseColors[frame[j]].b; 372 rgb += 3; 373 } 374 ConvertRGBtoYV12(MooseFrameRGB, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, 0, 100); 375 } 376 377 free(RawMooseData); 378 379 /* set the start frame */ 380 i = 0; 381 if (nodelay) { 382 fpsdelay = 0; 383 } else { 384 fpsdelay = 1000 / fps; 385 } 386 387 displayrect.x = 0; 388 displayrect.y = 0; 389 displayrect.w = window_w; 390 displayrect.h = window_h; 391 392 /* Ignore key up events, they don't even get filtered */ 393 SDL_EventState(SDL_KEYUP, SDL_IGNORE); 394 395 /* Loop, waiting for QUIT or RESIZE */ 396 while (!done) { 397 while (SDL_PollEvent(&event)) { 398 switch (event.type) { 399 case SDL_WINDOWEVENT: 400 if (event.window.event == SDL_WINDOWEVENT_RESIZED) { 401 SDL_RenderSetViewport(renderer, NULL); 402 displayrect.w = window_w = event.window.data1; 403 displayrect.h = window_h = event.window.data2; 404 } 405 break; 406 case SDL_MOUSEBUTTONDOWN: 407 displayrect.x = event.button.x - window_w / 2; 408 displayrect.y = event.button.y - window_h / 2; 409 break; 410 case SDL_MOUSEMOTION: 411 if (event.motion.state) { 412 displayrect.x = event.motion.x - window_w / 2; 413 displayrect.y = event.motion.y - window_h / 2; 414 } 415 break; 416 case SDL_KEYDOWN: 417 if (event.key.keysym.sym == SDLK_SPACE) { 418 paused = !paused; 419 break; 420 } 421 if (event.key.keysym.sym != SDLK_ESCAPE) { 422 break; 423 } 424 case SDL_QUIT: 425 done = SDL_TRUE; 426 break; 427 } 428 } 429 SDL_Delay(fpsdelay); 430 431 if (!paused) { 432 i = (i + 1) % MOOSEFRAMES_COUNT; 433 434 SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W*SDL_BYTESPERPIXEL(pixel_format)); 435 } 436 SDL_RenderClear(renderer); 437 SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect); 438 SDL_RenderPresent(renderer); 439 } 440 SDL_DestroyRenderer(renderer); 441 quit(0); 442 return 0; 443 } 444 445 /* vi: set ts=4 sw=4 expandtab: */ 446