00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "race.h"
00019 #include "utils.h"
00020 #include "mmfile.h"
00021 #include "int_types.h"
00022 #include <assert.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <stdarg.h>
00026 #include <unistd.h>
00027 #include <limits.h>
00028 #include <time.h>
00029 #include <math.h>
00030 #include <SDL.h>
00031
00032 #ifndef min
00033 # define min(a, b) ((a) <= (b) ? (a) : (b))
00034 #endif
00035
00036 void
00037 eperror(const char *str)
00038 {
00039 perror(str);
00040 exit(EXIT_FAILURE);
00041 }
00042
00043 void
00044 eprintf(const char *fmt, ...)
00045 {
00046 va_list ap;
00047
00048 va_start(ap, fmt);
00049 vfprintf(stderr, fmt, ap);
00050 va_end(ap);
00051 exit(EXIT_FAILURE);
00052 }
00053
00054 void
00055 usage(const char *progname)
00056 {
00057 if (strrchr(progname, '/') != NULL)
00058 progname = strrchr(progname, '/') + 1;
00059 fprintf(stderr, "usage: %s file.ogg\n", progname);
00060 exit(EXIT_SUCCESS);
00061 }
00062
00063 struct audiobuf
00064 {
00065 char *buf;
00066 int off, bytes, size;
00067 };
00068
00069 static void
00070 audio_cb(void *userdata, Uint8 * stream, int len)
00071 {
00072 struct audiobuf *abuf = userdata;
00073 int to_copy = min(len, abuf->bytes);
00074
00075 memcpy(stream, abuf->buf + abuf->off, to_copy);
00076 abuf->bytes -= to_copy;
00077 abuf->off += to_copy;
00078 }
00079
00080 int
00081 main(int argc, char **argv)
00082 {
00083 char *file = NULL;
00084 int have_video = 0, have_audio = 0;
00085 unsigned h = 0, w = 0;
00086 float fps = 0.0;
00087 unsigned ch = 0, hz = 0;
00088 struct audiobuf abuf;
00089 int end = 0;
00090 SDL_Surface *display = NULL;
00091 SDL_Overlay *ovl = NULL;
00092 SDL_Event event;
00093 mm_file media;
00094
00095 if (argc > 1)
00096 file = argv[1];
00097 else
00098 usage(argv[0]);
00099
00100 if (mm_open(&media, file) <= 0)
00101 eprintf("No audio or video in `%s'\n", file);
00102
00103 if (mm_video_info(&media, &w, &h, &fps) >= 0)
00104 {
00105 printf("Video data: %dx%d, %gfps\n", w, h, fps);
00106 have_video = 1;
00107 }
00108
00109 if (mm_audio_info(&media, &ch, &hz) >= 0)
00110 {
00111 printf("Audio data: %s, %dHz\n", (ch == 1) ? "mono" : "stereo", hz);
00112 have_audio = 1;
00113 }
00114
00115 if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0)
00116 eprintf("Sdl init failed: %s\n", SDL_GetError());
00117
00118 if (have_video)
00119 {
00120 if ((display = SDL_SetVideoMode(w, h, 24,
00121 SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
00122 eprintf("SDL_SetVideoMode: %s\n", SDL_GetError());
00123
00124 if ((ovl = SDL_CreateYUVOverlay(w, h,
00125 SDL_YV12_OVERLAY, display)) == NULL)
00126 eprintf("SDL_CreateYUVOverlay: %s\n", SDL_GetError());
00127 }
00128
00129 if (have_audio)
00130 {
00131 int bytes;
00132 int bps;
00133 double tdiff;
00134 SDL_AudioSpec desired;
00135
00136 desired.channels = ch;
00137 desired.freq = hz;
00138 desired.format = AUDIO_U8;
00139 bps = ch * 1;
00140 desired.samples = 4096;
00141 desired.callback = audio_cb;
00142 desired.userdata = &abuf;
00143 if (SDL_OpenAudio(&desired, NULL) < 0)
00144 eprintf("SDL_OpenAudio: %s\n", SDL_GetError());
00145
00146 abuf.size = 4 * 4096;
00147 abuf.off = 0;
00148 abuf.bytes = 0;
00149 abuf.buf = xmalloc(abuf.size);
00150
00151 tdiff = get_time();
00152 while ((bytes = mm_decode_audio(&media,
00153 abuf.buf + abuf.bytes, abuf.size - abuf.bytes)) > 0)
00154 {
00155 abuf.bytes += bytes;
00156 if (abuf.size - abuf.bytes <= 4096)
00157 abuf.buf = xrealloc(abuf.buf, abuf.size *= 2);
00158 };
00159 if (bytes < 0)
00160 eperror("convert_audio");
00161
00162 printf("Decoding: %.3f seconds\n", get_time() - tdiff);
00163 printf("Audio: %d samples, %.2f seconds\n", abuf.bytes / bps,
00164 (double) (abuf.bytes) / bps / desired.freq);
00165
00166 SDL_PauseAudio(0);
00167 }
00168
00169 while (!end)
00170 {
00171 while (SDL_PollEvent(&event))
00172 switch (event.type)
00173 {
00174 case SDL_QUIT:
00175 end = 1;
00176 break;
00177 case SDL_KEYDOWN:
00178 if (event.key.keysym.sym == SDLK_q
00179 || event.key.keysym.sym == SDLK_ESCAPE)
00180 end = 1;
00181 break;
00182 default:
00183 break;
00184 }
00185
00186 if (have_video && !end)
00187 {
00188 static double oldt, newt;
00189
00190 if (mm_decode_video(&media, ovl) > 0)
00191 {
00192 SDL_Rect r = { 0, 0, w, h };
00193 newt = 1 / fps + oldt - get_time();
00194 if (newt > 0)
00195 SDL_Delay(newt * 1000);
00196 SDL_DisplayYUVOverlay(ovl, &r);
00197 oldt = get_time();
00198 }
00199 else
00200 end = 1;
00201 }
00202
00203 if (have_audio && abuf.bytes <= 0)
00204 end = 1;
00205
00206 if (!have_video)
00207 SDL_Delay(100);
00208 }
00209
00210 if (have_audio)
00211 {
00212 SDL_PauseAudio(1);
00213 free(abuf.buf);
00214 }
00215
00216 if (have_video)
00217 {
00218 SDL_FreeYUVOverlay(ovl);
00219 }
00220
00221 SDL_Quit();
00222 mm_close(&media);
00223
00224 return EXIT_SUCCESS;
00225 }
00226
00227