Mercurial > mplayer.hg
comparison libao2/ao_sdl.c @ 28882:15f93fd5cd48
Reuse libavutil fifo code instead of reimplementing it over and over.
author | reimar |
---|---|
date | Mon, 09 Mar 2009 18:21:47 +0000 |
parents | 9a5b8c2ed6de |
children | f951680cfea2 |
comparison
equal
deleted
inserted
replaced
28881:340e60d5b46b | 28882:15f93fd5cd48 |
---|---|
1 /* | 1 /* |
2 * SDLlib audio output driver for MPlayer | 2 * SDLlib audio output driver for MPlayer |
3 * | 3 * |
4 * Copyleft 2001 by Felix Bünemann (atmosfear@users.sf.net) | 4 * Copyleft 2001 by Felix Bünemann (atmosfear@users.sf.net) |
5 * | |
6 * Thanks to Arpi for nice ringbuffer-code! | |
7 * | 5 * |
8 * This file is part of MPlayer. | 6 * This file is part of MPlayer. |
9 * | 7 * |
10 * MPlayer is free software; you can redistribute it and/or modify | 8 * MPlayer is free software; you can redistribute it and/or modify |
11 * it under the terms of the GNU General Public License as published by | 9 * it under the terms of the GNU General Public License as published by |
34 #include "audio_out_internal.h" | 32 #include "audio_out_internal.h" |
35 #include "libaf/af_format.h" | 33 #include "libaf/af_format.h" |
36 #include <SDL.h> | 34 #include <SDL.h> |
37 #include "osdep/timer.h" | 35 #include "osdep/timer.h" |
38 | 36 |
39 #include "libvo/fastmemcpy.h" | 37 #include "libavutil/fifo.h" |
40 | 38 |
41 static const ao_info_t info = | 39 static const ao_info_t info = |
42 { | 40 { |
43 "SDLlib audio output", | 41 "SDLlib audio output", |
44 "sdl", | 42 "sdl", |
58 #define SAMPLESIZE 1024 | 56 #define SAMPLESIZE 1024 |
59 #endif | 57 #endif |
60 | 58 |
61 #define CHUNK_SIZE 4096 | 59 #define CHUNK_SIZE 4096 |
62 #define NUM_CHUNKS 8 | 60 #define NUM_CHUNKS 8 |
63 // This type of ring buffer may never fill up completely, at least | 61 #define BUFFSIZE (NUM_CHUNKS * CHUNK_SIZE) |
64 // one byte must always be unused. | 62 |
65 // For performance reasons (alignment etc.) one whole chunk always stays | 63 static AVFifoBuffer *buffer; |
66 // empty, not only one byte. | 64 |
67 #define BUFFSIZE ((NUM_CHUNKS + 1) * CHUNK_SIZE) | |
68 | |
69 static unsigned char *buffer; | |
70 | |
71 // may only be modified by SDL's playback thread or while it is stopped | |
72 static volatile int read_pos; | |
73 // may only be modified by mplayer's thread | |
74 static volatile int write_pos; | |
75 #ifdef USE_SDL_INTERNAL_MIXER | 65 #ifdef USE_SDL_INTERNAL_MIXER |
76 static unsigned char volume=SDL_MIX_MAXVOLUME; | 66 static unsigned char volume=SDL_MIX_MAXVOLUME; |
77 #endif | 67 #endif |
78 | 68 |
79 // may only be called by mplayer's thread | |
80 // return value may change between immediately following two calls, | |
81 // and the real number of free bytes might be larger! | |
82 static int buf_free(void) { | |
83 int free = read_pos - write_pos - CHUNK_SIZE; | |
84 if (free < 0) free += BUFFSIZE; | |
85 return free; | |
86 } | |
87 | |
88 // may only be called by SDL's playback thread | |
89 // return value may change between immediately following two calls, | |
90 // and the real number of buffered bytes might be larger! | |
91 static int buf_used(void) { | |
92 int used = write_pos - read_pos; | |
93 if (used < 0) used += BUFFSIZE; | |
94 return used; | |
95 } | |
96 | |
97 static int write_buffer(unsigned char* data,int len){ | 69 static int write_buffer(unsigned char* data,int len){ |
98 int first_len = BUFFSIZE - write_pos; | 70 int free = BUFFSIZE - av_fifo_size(buffer); |
99 int free = buf_free(); | |
100 if (len > free) len = free; | 71 if (len > free) len = free; |
101 if (first_len > len) first_len = len; | 72 return av_fifo_generic_write(buffer, data, len, NULL); |
102 // till end of buffer | 73 } |
103 fast_memcpy (&buffer[write_pos], data, first_len); | 74 |
104 if (len > first_len) { // we have to wrap around | 75 #ifdef USE_SDL_INTERNAL_MIXER |
105 // remaining part from beginning of buffer | 76 static void mix_audio(void *dst, void *src, int len) { |
106 fast_memcpy (buffer, &data[first_len], len - first_len); | 77 SDL_MixAudio(dst, src, len, volume); |
107 } | 78 } |
108 write_pos = (write_pos + len) % BUFFSIZE; | 79 #endif |
109 return len; | |
110 } | |
111 | 80 |
112 static int read_buffer(unsigned char* data,int len){ | 81 static int read_buffer(unsigned char* data,int len){ |
113 int first_len = BUFFSIZE - read_pos; | 82 int buffered = av_fifo_size(buffer); |
114 int buffered = buf_used(); | |
115 if (len > buffered) len = buffered; | 83 if (len > buffered) len = buffered; |
116 if (first_len > len) first_len = len; | |
117 // till end of buffer | |
118 #ifdef USE_SDL_INTERNAL_MIXER | 84 #ifdef USE_SDL_INTERNAL_MIXER |
119 SDL_MixAudio (data, &buffer[read_pos], first_len, volume); | 85 return av_fifo_generic_read(buffer, data, len, mix_audio); |
120 #else | 86 #else |
121 fast_memcpy (data, &buffer[read_pos], first_len); | 87 return av_fifo_generic_read(buffer, data, len, NULL); |
122 #endif | 88 #endif |
123 if (len > first_len) { // we have to wrap around | |
124 // remaining part from beginning of buffer | |
125 #ifdef USE_SDL_INTERNAL_MIXER | |
126 SDL_MixAudio (&data[first_len], buffer, len - first_len, volume); | |
127 #else | |
128 fast_memcpy (&data[first_len], buffer, len - first_len); | |
129 #endif | |
130 } | |
131 read_pos = (read_pos + len) % BUFFSIZE; | |
132 return len; | |
133 } | 89 } |
134 | 90 |
135 // end ring buffer stuff | 91 // end ring buffer stuff |
136 | 92 |
137 | 93 |
173 | 129 |
174 /* SDL Audio Specifications */ | 130 /* SDL Audio Specifications */ |
175 SDL_AudioSpec aspec, obtained; | 131 SDL_AudioSpec aspec, obtained; |
176 | 132 |
177 /* Allocate ring-buffer memory */ | 133 /* Allocate ring-buffer memory */ |
178 buffer = (unsigned char *) malloc(BUFFSIZE); | 134 buffer = av_fifo_alloc(BUFFSIZE); |
179 | 135 |
180 mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_SDL_INFO, rate, (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format)); | 136 mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_SDL_INFO, rate, (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format)); |
181 | 137 |
182 if(ao_subdevice) { | 138 if(ao_subdevice) { |
183 setenv("SDL_AUDIODRIVER", ao_subdevice, 1); | 139 setenv("SDL_AUDIODRIVER", ao_subdevice, 1); |
276 | 232 |
277 mp_msg(MSGT_AO,MSGL_V,"SDL: buf size = %d\n",obtained.size); | 233 mp_msg(MSGT_AO,MSGL_V,"SDL: buf size = %d\n",obtained.size); |
278 ao_data.buffersize=obtained.size; | 234 ao_data.buffersize=obtained.size; |
279 ao_data.outburst = CHUNK_SIZE; | 235 ao_data.outburst = CHUNK_SIZE; |
280 | 236 |
281 reset(); | |
282 /* unsilence audio, if callback is ready */ | 237 /* unsilence audio, if callback is ready */ |
283 SDL_PauseAudio(0); | 238 SDL_PauseAudio(0); |
284 | 239 |
285 return 1; | 240 return 1; |
286 } | 241 } |
290 mp_msg(MSGT_AO,MSGL_V,"SDL: Audio Subsystem shutting down!\n"); | 245 mp_msg(MSGT_AO,MSGL_V,"SDL: Audio Subsystem shutting down!\n"); |
291 if (!immed) | 246 if (!immed) |
292 usec_sleep(get_delay() * 1000 * 1000); | 247 usec_sleep(get_delay() * 1000 * 1000); |
293 SDL_CloseAudio(); | 248 SDL_CloseAudio(); |
294 SDL_QuitSubSystem(SDL_INIT_AUDIO); | 249 SDL_QuitSubSystem(SDL_INIT_AUDIO); |
250 av_fifo_free(buffer); | |
295 } | 251 } |
296 | 252 |
297 // stop playing and empty buffers (for seeking/pause) | 253 // stop playing and empty buffers (for seeking/pause) |
298 static void reset(void){ | 254 static void reset(void){ |
299 | 255 |
300 //printf("SDL: reset called!\n"); | 256 //printf("SDL: reset called!\n"); |
301 | 257 |
302 SDL_PauseAudio(1); | 258 SDL_PauseAudio(1); |
303 /* Reset ring-buffer state */ | 259 /* Reset ring-buffer state */ |
304 read_pos = 0; | 260 av_fifo_reset(buffer); |
305 write_pos = 0; | |
306 SDL_PauseAudio(0); | 261 SDL_PauseAudio(0); |
307 } | 262 } |
308 | 263 |
309 // stop playing, keep buffers (for pause) | 264 // stop playing, keep buffers (for pause) |
310 static void audio_pause(void) | 265 static void audio_pause(void) |
323 } | 278 } |
324 | 279 |
325 | 280 |
326 // return: how many bytes can be played without blocking | 281 // return: how many bytes can be played without blocking |
327 static int get_space(void){ | 282 static int get_space(void){ |
328 return buf_free(); | 283 return BUFFSIZE - av_fifo_size(buffer); |
329 } | 284 } |
330 | 285 |
331 // plays 'len' bytes of 'data' | 286 // plays 'len' bytes of 'data' |
332 // it should round it down to outburst*n | 287 // it should round it down to outburst*n |
333 // return: number of bytes played | 288 // return: number of bytes played |
350 #endif | 305 #endif |
351 } | 306 } |
352 | 307 |
353 // return: delay in seconds between first and last sample in buffer | 308 // return: delay in seconds between first and last sample in buffer |
354 static float get_delay(void){ | 309 static float get_delay(void){ |
355 int buffered = BUFFSIZE - CHUNK_SIZE - buf_free(); // could be less | 310 int buffered = av_fifo_size(buffer); // could be less |
356 return (float)(buffered + ao_data.buffersize)/(float)ao_data.bps; | 311 return (float)(buffered + ao_data.buffersize)/(float)ao_data.bps; |
357 } | 312 } |
358 | 313 |
359 | 314 |
360 | 315 |