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