1 | /* |
2 | Copyright (C) 1997-2021 Sam Lantinga <slouken@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 | |
21 | #ifdef __EMSCRIPTEN__ |
22 | #include <emscripten/emscripten.h> |
23 | #endif |
24 | |
25 | #include "SDL.h" |
26 | |
27 | #include "testyuv_cvt.h" |
28 | |
29 | #define MOOSEPIC_W 64 |
30 | #define MOOSEPIC_H 88 |
31 | |
32 | #define MOOSEFRAME_SIZE (MOOSEPIC_W * MOOSEPIC_H) |
33 | #define MOOSEFRAMES_COUNT 10 |
34 | |
35 | SDL_Color MooseColors[84] = { |
36 | {49, 49, 49, SDL_ALPHA_OPAQUE} |
37 | , {66, 24, 0, SDL_ALPHA_OPAQUE} |
38 | , {66, 33, 0, SDL_ALPHA_OPAQUE} |
39 | , {66, 66, 66, SDL_ALPHA_OPAQUE} |
40 | , |
41 | {66, 115, 49, SDL_ALPHA_OPAQUE} |
42 | , {74, 33, 0, SDL_ALPHA_OPAQUE} |
43 | , {74, 41, 16, SDL_ALPHA_OPAQUE} |
44 | , {82, 33, 8, SDL_ALPHA_OPAQUE} |
45 | , |
46 | {82, 41, 8, SDL_ALPHA_OPAQUE} |
47 | , {82, 49, 16, SDL_ALPHA_OPAQUE} |
48 | , {82, 82, 82, SDL_ALPHA_OPAQUE} |
49 | , {90, 41, 8, SDL_ALPHA_OPAQUE} |
50 | , |
51 | {90, 41, 16, SDL_ALPHA_OPAQUE} |
52 | , {90, 57, 24, SDL_ALPHA_OPAQUE} |
53 | , {99, 49, 16, SDL_ALPHA_OPAQUE} |
54 | , {99, 66, 24, SDL_ALPHA_OPAQUE} |
55 | , |
56 | {99, 66, 33, SDL_ALPHA_OPAQUE} |
57 | , {99, 74, 33, SDL_ALPHA_OPAQUE} |
58 | , {107, 57, 24, SDL_ALPHA_OPAQUE} |
59 | , {107, 82, 41, SDL_ALPHA_OPAQUE} |
60 | , |
61 | {115, 57, 33, SDL_ALPHA_OPAQUE} |
62 | , {115, 66, 33, SDL_ALPHA_OPAQUE} |
63 | , {115, 66, 41, SDL_ALPHA_OPAQUE} |
64 | , {115, 74, 0, SDL_ALPHA_OPAQUE} |
65 | , |
66 | {115, 90, 49, SDL_ALPHA_OPAQUE} |
67 | , {115, 115, 115, SDL_ALPHA_OPAQUE} |
68 | , {123, 82, 0, SDL_ALPHA_OPAQUE} |
69 | , {123, 99, 57, SDL_ALPHA_OPAQUE} |
70 | , |
71 | {132, 66, 41, SDL_ALPHA_OPAQUE} |
72 | , {132, 74, 41, SDL_ALPHA_OPAQUE} |
73 | , {132, 90, 8, SDL_ALPHA_OPAQUE} |
74 | , {132, 99, 33, SDL_ALPHA_OPAQUE} |
75 | , |
76 | {132, 99, 66, SDL_ALPHA_OPAQUE} |
77 | , {132, 107, 66, SDL_ALPHA_OPAQUE} |
78 | , {140, 74, 49, SDL_ALPHA_OPAQUE} |
79 | , {140, 99, 16, SDL_ALPHA_OPAQUE} |
80 | , |
81 | {140, 107, 74, SDL_ALPHA_OPAQUE} |
82 | , {140, 115, 74, SDL_ALPHA_OPAQUE} |
83 | , {148, 107, 24, SDL_ALPHA_OPAQUE} |
84 | , {148, 115, 82, SDL_ALPHA_OPAQUE} |
85 | , |
86 | {148, 123, 74, SDL_ALPHA_OPAQUE} |
87 | , {148, 123, 90, SDL_ALPHA_OPAQUE} |
88 | , {156, 115, 33, SDL_ALPHA_OPAQUE} |
89 | , {156, 115, 90, SDL_ALPHA_OPAQUE} |
90 | , |
91 | {156, 123, 82, SDL_ALPHA_OPAQUE} |
92 | , {156, 132, 82, SDL_ALPHA_OPAQUE} |
93 | , {156, 132, 99, SDL_ALPHA_OPAQUE} |
94 | , {156, 156, 156, SDL_ALPHA_OPAQUE} |
95 | , |
96 | {165, 123, 49, SDL_ALPHA_OPAQUE} |
97 | , {165, 123, 90, SDL_ALPHA_OPAQUE} |
98 | , {165, 132, 82, SDL_ALPHA_OPAQUE} |
99 | , {165, 132, 90, SDL_ALPHA_OPAQUE} |
100 | , |
101 | {165, 132, 99, SDL_ALPHA_OPAQUE} |
102 | , {165, 140, 90, SDL_ALPHA_OPAQUE} |
103 | , {173, 132, 57, SDL_ALPHA_OPAQUE} |
104 | , {173, 132, 99, SDL_ALPHA_OPAQUE} |
105 | , |
106 | {173, 140, 107, SDL_ALPHA_OPAQUE} |
107 | , {173, 140, 115, SDL_ALPHA_OPAQUE} |
108 | , {173, 148, 99, SDL_ALPHA_OPAQUE} |
109 | , {173, 173, 173, SDL_ALPHA_OPAQUE} |
110 | , |
111 | {181, 140, 74, SDL_ALPHA_OPAQUE} |
112 | , {181, 148, 115, SDL_ALPHA_OPAQUE} |
113 | , {181, 148, 123, SDL_ALPHA_OPAQUE} |
114 | , {181, 156, 107, SDL_ALPHA_OPAQUE} |
115 | , |
116 | {189, 148, 123, SDL_ALPHA_OPAQUE} |
117 | , {189, 156, 82, SDL_ALPHA_OPAQUE} |
118 | , {189, 156, 123, SDL_ALPHA_OPAQUE} |
119 | , {189, 156, 132, SDL_ALPHA_OPAQUE} |
120 | , |
121 | {189, 189, 189, SDL_ALPHA_OPAQUE} |
122 | , {198, 156, 123, SDL_ALPHA_OPAQUE} |
123 | , {198, 165, 132, SDL_ALPHA_OPAQUE} |
124 | , {206, 165, 99, SDL_ALPHA_OPAQUE} |
125 | , |
126 | {206, 165, 132, SDL_ALPHA_OPAQUE} |
127 | , {206, 173, 140, SDL_ALPHA_OPAQUE} |
128 | , {206, 206, 206, SDL_ALPHA_OPAQUE} |
129 | , {214, 173, 115, SDL_ALPHA_OPAQUE} |
130 | , |
131 | {214, 173, 140, SDL_ALPHA_OPAQUE} |
132 | , {222, 181, 148, SDL_ALPHA_OPAQUE} |
133 | , {222, 189, 132, SDL_ALPHA_OPAQUE} |
134 | , {222, 189, 156, SDL_ALPHA_OPAQUE} |
135 | , |
136 | {222, 222, 222, SDL_ALPHA_OPAQUE} |
137 | , {231, 198, 165, SDL_ALPHA_OPAQUE} |
138 | , {231, 231, 231, SDL_ALPHA_OPAQUE} |
139 | , {239, 206, 173, SDL_ALPHA_OPAQUE} |
140 | }; |
141 | |
142 | Uint8 MooseFrame[MOOSEFRAMES_COUNT][MOOSEFRAME_SIZE*2]; |
143 | SDL_Texture *MooseTexture; |
144 | SDL_Rect displayrect; |
145 | int window_w; |
146 | int window_h; |
147 | SDL_Renderer *renderer; |
148 | int paused = 0; |
149 | int i; |
150 | SDL_bool done = SDL_FALSE; |
151 | static int fpsdelay; |
152 | |
153 | /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
154 | static void |
155 | quit(int rc) |
156 | { |
157 | SDL_Quit(); |
158 | exit(rc); |
159 | } |
160 | |
161 | static void |
162 | PrintUsage(char *argv0) |
163 | { |
164 | SDL_Log("Usage: %s [arg] [arg] [arg] ...\n" , argv0); |
165 | SDL_Log("\n" ); |
166 | SDL_Log("Where 'arg' is any of the following options:\n" ); |
167 | SDL_Log("\n" ); |
168 | SDL_Log(" -fps <frames per second>\n" ); |
169 | SDL_Log(" -nodelay\n" ); |
170 | SDL_Log(" -format <fmt> (one of the: YV12, IYUV, YUY2, UYVY, YVYU)\n" ); |
171 | SDL_Log(" -scale <scale factor> (initial scale of the overlay)\n" ); |
172 | SDL_Log(" -help (shows this help)\n" ); |
173 | SDL_Log("\n" ); |
174 | SDL_Log("Press ESC to exit, or SPACE to freeze the movie while application running.\n" ); |
175 | SDL_Log("\n" ); |
176 | } |
177 | |
178 | void |
179 | loop() |
180 | { |
181 | SDL_Event event; |
182 | |
183 | while (SDL_PollEvent(&event)) { |
184 | switch (event.type) { |
185 | case SDL_WINDOWEVENT: |
186 | if (event.window.event == SDL_WINDOWEVENT_RESIZED) { |
187 | SDL_RenderSetViewport(renderer, NULL); |
188 | displayrect.w = window_w = event.window.data1; |
189 | displayrect.h = window_h = event.window.data2; |
190 | } |
191 | break; |
192 | case SDL_MOUSEBUTTONDOWN: |
193 | displayrect.x = event.button.x - window_w / 2; |
194 | displayrect.y = event.button.y - window_h / 2; |
195 | break; |
196 | case SDL_MOUSEMOTION: |
197 | if (event.motion.state) { |
198 | displayrect.x = event.motion.x - window_w / 2; |
199 | displayrect.y = event.motion.y - window_h / 2; |
200 | } |
201 | break; |
202 | case SDL_KEYDOWN: |
203 | if (event.key.keysym.sym == SDLK_SPACE) { |
204 | paused = !paused; |
205 | break; |
206 | } |
207 | if (event.key.keysym.sym != SDLK_ESCAPE) { |
208 | break; |
209 | } |
210 | case SDL_QUIT: |
211 | done = SDL_TRUE; |
212 | break; |
213 | } |
214 | } |
215 | |
216 | #ifndef __EMSCRIPTEN__ |
217 | SDL_Delay(fpsdelay); |
218 | #endif |
219 | |
220 | if (!paused) { |
221 | i = (i + 1) % MOOSEFRAMES_COUNT; |
222 | |
223 | SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W); |
224 | } |
225 | SDL_RenderClear(renderer); |
226 | SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect); |
227 | SDL_RenderPresent(renderer); |
228 | |
229 | #ifdef __EMSCRIPTEN__ |
230 | if (done) { |
231 | emscripten_cancel_main_loop(); |
232 | } |
233 | #endif |
234 | } |
235 | |
236 | int |
237 | main(int argc, char **argv) |
238 | { |
239 | Uint8 *RawMooseData; |
240 | SDL_RWops *handle; |
241 | SDL_Window *window; |
242 | int j; |
243 | int fps = 12; |
244 | int nodelay = 0; |
245 | int scale = 5; |
246 | |
247 | /* Enable standard application logging */ |
248 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |
249 | |
250 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { |
251 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n" , SDL_GetError()); |
252 | return 3; |
253 | } |
254 | |
255 | while (argc > 1) { |
256 | if (SDL_strcmp(argv[1], "-fps" ) == 0) { |
257 | if (argv[2]) { |
258 | fps = SDL_atoi(argv[2]); |
259 | if (fps == 0) { |
260 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, |
261 | "The -fps option requires an argument [from 1 to 1000], default is 12.\n" ); |
262 | quit(10); |
263 | } |
264 | if ((fps < 0) || (fps > 1000)) { |
265 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, |
266 | "The -fps option must be in range from 1 to 1000, default is 12.\n" ); |
267 | quit(10); |
268 | } |
269 | argv += 2; |
270 | argc -= 2; |
271 | } else { |
272 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, |
273 | "The -fps option requires an argument [from 1 to 1000], default is 12.\n" ); |
274 | quit(10); |
275 | } |
276 | } else if (SDL_strcmp(argv[1], "-nodelay" ) == 0) { |
277 | nodelay = 1; |
278 | argv += 1; |
279 | argc -= 1; |
280 | } else if (SDL_strcmp(argv[1], "-scale" ) == 0) { |
281 | if (argv[2]) { |
282 | scale = SDL_atoi(argv[2]); |
283 | if (scale == 0) { |
284 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, |
285 | "The -scale option requires an argument [from 1 to 50], default is 5.\n" ); |
286 | quit(10); |
287 | } |
288 | if ((scale < 0) || (scale > 50)) { |
289 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, |
290 | "The -scale option must be in range from 1 to 50, default is 5.\n" ); |
291 | quit(10); |
292 | } |
293 | argv += 2; |
294 | argc -= 2; |
295 | } else { |
296 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, |
297 | "The -fps option requires an argument [from 1 to 1000], default is 12.\n" ); |
298 | quit(10); |
299 | } |
300 | } else if ((SDL_strcmp(argv[1], "-help" ) == 0) |
301 | || (SDL_strcmp(argv[1], "-h" ) == 0)) { |
302 | PrintUsage(argv[0]); |
303 | quit(0); |
304 | } else { |
305 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized option: %s.\n" , argv[1]); |
306 | quit(10); |
307 | } |
308 | break; |
309 | } |
310 | |
311 | RawMooseData = (Uint8 *) SDL_malloc(MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT); |
312 | if (RawMooseData == NULL) { |
313 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't allocate memory for movie !\n" ); |
314 | quit(1); |
315 | } |
316 | |
317 | /* load the trojan moose images */ |
318 | handle = SDL_RWFromFile("moose.dat" , "rb" ); |
319 | if (handle == NULL) { |
320 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n" ); |
321 | SDL_free(RawMooseData); |
322 | quit(2); |
323 | } |
324 | |
325 | SDL_RWread(handle, RawMooseData, MOOSEFRAME_SIZE, MOOSEFRAMES_COUNT); |
326 | |
327 | SDL_RWclose(handle); |
328 | |
329 | /* Create the window and renderer */ |
330 | window_w = MOOSEPIC_W * scale; |
331 | window_h = MOOSEPIC_H * scale; |
332 | window = SDL_CreateWindow("Happy Moose" , |
333 | SDL_WINDOWPOS_UNDEFINED, |
334 | SDL_WINDOWPOS_UNDEFINED, |
335 | window_w, window_h, |
336 | SDL_WINDOW_RESIZABLE); |
337 | if (!window) { |
338 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n" , SDL_GetError()); |
339 | SDL_free(RawMooseData); |
340 | quit(4); |
341 | } |
342 | |
343 | renderer = SDL_CreateRenderer(window, -1, 0); |
344 | if (!renderer) { |
345 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n" , SDL_GetError()); |
346 | SDL_free(RawMooseData); |
347 | quit(4); |
348 | } |
349 | |
350 | MooseTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H); |
351 | if (!MooseTexture) { |
352 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n" , SDL_GetError()); |
353 | SDL_free(RawMooseData); |
354 | quit(5); |
355 | } |
356 | /* Uncomment this to check vertex color with a YUV texture */ |
357 | /* SDL_SetTextureColorMod(MooseTexture, 0xff, 0x80, 0x80); */ |
358 | |
359 | for (i = 0; i < MOOSEFRAMES_COUNT; i++) { |
360 | Uint8 MooseFrameRGB[MOOSEFRAME_SIZE*3]; |
361 | Uint8 *rgb; |
362 | Uint8 *frame; |
363 | |
364 | rgb = MooseFrameRGB; |
365 | frame = RawMooseData + i * MOOSEFRAME_SIZE; |
366 | for (j = 0; j < MOOSEFRAME_SIZE; ++j) { |
367 | rgb[0] = MooseColors[frame[j]].r; |
368 | rgb[1] = MooseColors[frame[j]].g; |
369 | rgb[2] = MooseColors[frame[j]].b; |
370 | rgb += 3; |
371 | } |
372 | ConvertRGBtoYUV(SDL_PIXELFORMAT_YV12, MooseFrameRGB, MOOSEPIC_W*3, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, |
373 | SDL_GetYUVConversionModeForResolution(MOOSEPIC_W, MOOSEPIC_H), |
374 | 0, 100); |
375 | } |
376 | |
377 | SDL_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 | #ifdef __EMSCRIPTEN__ |
397 | emscripten_set_main_loop(loop, nodelay ? 0 : fps, 1); |
398 | #else |
399 | while (!done) { |
400 | loop(); |
401 | } |
402 | #endif |
403 | |
404 | SDL_DestroyRenderer(renderer); |
405 | quit(0); |
406 | return 0; |
407 | } |
408 | |
409 | /* vi: set ts=4 sw=4 expandtab: */ |
410 | |