Cast a malloc() call to a specific pointer type.
2 * TheoraPlay; multithreaded Ogg Theora/Ogg Vorbis decoding.
4 * Please see the file LICENSE.txt in the source's root directory.
6 * This file written by Ryan C. Gordon.
10 * This is meant to be a dirt simple test case. If you want a big, robust
11 * version that handles lots of strange variations, try sdltheoraplay.c
19 #include "theoraplay.h"
22 static Uint32 baseticks = 0;
24 typedef struct AudioQueue
26 const THEORAPLAY_AudioPacket *audio;
28 struct AudioQueue *next;
31 static volatile AudioQueue *audio_queue = NULL;
32 static volatile AudioQueue *audio_queue_tail = NULL;
34 static void SDLCALL audio_callback(void *userdata, Uint8 *stream, int len)
36 // !!! FIXME: this should refuse to play if item->playms is in the future.
37 //const Uint32 now = SDL_GetTicks() - baseticks;
38 Sint16 *dst = (Sint16 *) stream;
40 while (audio_queue && (len > 0))
42 volatile AudioQueue *item = audio_queue;
43 AudioQueue *next = item->next;
44 const int channels = item->audio->channels;
46 const float *src = item->audio->samples + (item->offset * channels);
47 int cpy = (item->audio->frames - item->offset) * channels;
50 if (cpy > (len / sizeof (Sint16)))
51 cpy = len / sizeof (Sint16);
53 for (i = 0; i < cpy; i++)
55 const float val = *(src++);
61 *(dst++) = (Sint16) (val * 32767.0f);
64 item->offset += (cpy / channels);
65 len -= cpy * sizeof (Sint16);
67 if (item->offset >= item->audio->frames)
69 THEORAPLAY_freeAudio(item->audio);
76 audio_queue_tail = NULL;
79 memset(dst, '\0', len);
83 static void queue_audio(const THEORAPLAY_AudioPacket *audio)
85 AudioQueue *item = (AudioQueue *) malloc(sizeof (AudioQueue));
88 THEORAPLAY_freeAudio(audio);
98 audio_queue_tail->next = item;
101 audio_queue_tail = item;
106 static void playfile(const char *fname)
108 THEORAPLAY_Decoder *decoder = NULL;
109 const THEORAPLAY_VideoFrame *video = NULL;
110 const THEORAPLAY_AudioPacket *audio = NULL;
111 SDL_Surface *screen = NULL;
112 SDL_Overlay *overlay = NULL;
119 printf("Trying file '%s' ...\n", fname);
121 decoder = THEORAPLAY_startDecodeFile(fname, 30, THEORAPLAY_VIDFMT_IYUV);
124 fprintf(stderr, "Failed to start decoding '%s'!\n", fname);
128 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) == -1)
130 fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
134 // wait until we have video and/or audio data, so we can set up hardware.
135 while (!audio || !video)
137 if (!audio) audio = THEORAPLAY_getAudio(decoder);
138 if (!video) video = THEORAPLAY_getVideo(decoder);
142 SDL_WM_SetCaption(fname, "TheoraPlay");
144 framems = (video->fps == 0.0) ? 0 : ((Uint32) (1000.0 / video->fps));
145 screen = SDL_SetVideoMode(video->width, video->height, 0, 0);
147 fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
148 else // software surface
150 // blank out the screen to start.
151 SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
154 overlay = SDL_CreateYUVOverlay(video->width, video->height,
155 SDL_IYUV_OVERLAY, screen);
157 fprintf(stderr, "YUV Overlay failed: %s\n", SDL_GetError());
160 initfailed = quit = (!screen || !overlay);
162 memset(&spec, '\0', sizeof (SDL_AudioSpec));
163 spec.freq = audio->freq;
164 spec.format = AUDIO_S16SYS;
165 spec.channels = audio->channels;
167 spec.callback = audio_callback;
168 initfailed = quit = (initfailed || (SDL_OpenAudio(&spec, NULL) != 0));
173 audio = THEORAPLAY_getAudio(decoder);
176 baseticks = SDL_GetTicks();
181 while (!quit && THEORAPLAY_isDecoding(decoder))
183 const Uint32 now = SDL_GetTicks() - baseticks;
186 video = THEORAPLAY_getVideo(decoder);
188 // Play video frames when it's time.
189 if (video && (video->playms <= now))
191 //printf("Play video frame (%u ms)!\n", video->playms);
192 if ( framems && ((now - video->playms) >= framems) )
194 // Skip frames to catch up, but keep track of the last one
195 // in case we catch up to a series of dupe frames, which
196 // means we'd have to draw that final frame and then wait for
198 const THEORAPLAY_VideoFrame *last = video;
199 while ((video = THEORAPLAY_getVideo(decoder)) != NULL)
201 THEORAPLAY_freeVideo(last);
203 if ((now - video->playms) < framems)
211 if (!video) // do nothing; we're far behind and out of options.
213 static int warned = 0;
217 fprintf(stderr, "WARNING: Playback can't keep up!\n");
221 else if (SDL_LockYUVOverlay(overlay) == -1)
223 static int warned = 0;
227 fprintf(stderr, "Couldn't lock YUV overlay: %s\n", SDL_GetError());
233 SDL_Rect dstrect = { 0, 0, video->width, video->height };
234 const int w = video->width;
235 const int h = video->height;
236 const Uint8 *y = (const Uint8 *) video->pixels;
237 const Uint8 *u = y + (w * h);
238 const Uint8 *v = u + ((w/2) * (h/2));
242 dst = overlay->pixels[0];
243 for (i = 0; i < h; i++, y += w, dst += overlay->pitches[0])
246 dst = overlay->pixels[1];
247 for (i = 0; i < h/2; i++, u += w/2, dst += overlay->pitches[1])
250 dst = overlay->pixels[2];
251 for (i = 0; i < h/2; i++, v += w/2, dst += overlay->pitches[1])
254 SDL_UnlockYUVOverlay(overlay);
256 if (SDL_DisplayYUVOverlay(overlay, &dstrect) != 0)
258 static int warned = 0;
262 fprintf(stderr, "Couldn't display YUV overlay: %s\n", SDL_GetError());
267 THEORAPLAY_freeVideo(video);
270 else // no new video frame? Give up some CPU.
275 while ((audio = THEORAPLAY_getAudio(decoder)) != NULL)
278 // Pump the event loop here.
279 while (screen && SDL_PollEvent(&event))
283 case SDL_VIDEOEXPOSE:
286 SDL_Rect dstrect = { 0, 0, screen->w, screen->h };
287 SDL_DisplayYUVOverlay(overlay, &dstrect);
296 if (event.key.keysym.sym == SDLK_ESCAPE)
303 // Drain out the audio queue.
307 quit = (audio_queue == NULL);
310 SDL_Delay(100); // wait for final audio packets to play out.
314 printf("Initialization failed!\n");
315 else if (THEORAPLAY_decodingError(decoder))
316 printf("There was an error decoding this file!\n");
318 printf("done with this file!\n");
320 if (overlay) SDL_FreeYUVOverlay(overlay);
321 if (video) THEORAPLAY_freeVideo(video);
322 if (audio) THEORAPLAY_freeAudio(audio);
323 if (decoder) THEORAPLAY_stopDecode(decoder);
328 int main(int argc, char **argv)
331 for (i = 1; i < argc; i++)
334 printf("done all files!\n");
339 // end of sdltheoraplay.c ...