diff 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
line wrap: on
line diff
--- a/libao2/ao_sdl.c	Mon Mar 09 17:25:43 2009 +0000
+++ b/libao2/ao_sdl.c	Mon Mar 09 18:21:47 2009 +0000
@@ -3,8 +3,6 @@
  *
  * Copyleft 2001 by Felix Bünemann (atmosfear@users.sf.net)
  *
- * Thanks to Arpi for nice ringbuffer-code!
- *
  * This file is part of MPlayer.
  *
  * MPlayer is free software; you can redistribute it and/or modify
@@ -36,7 +34,7 @@
 #include <SDL.h>
 #include "osdep/timer.h"
 
-#include "libvo/fastmemcpy.h"
+#include "libavutil/fifo.h"
 
 static const ao_info_t info = 
 {
@@ -60,76 +58,34 @@
 
 #define CHUNK_SIZE 4096
 #define NUM_CHUNKS 8
-// This type of ring buffer may never fill up completely, at least
-// one byte must always be unused.
-// For performance reasons (alignment etc.) one whole chunk always stays
-// empty, not only one byte.
-#define BUFFSIZE ((NUM_CHUNKS + 1) * CHUNK_SIZE)
+#define BUFFSIZE (NUM_CHUNKS * CHUNK_SIZE)
 
-static unsigned char *buffer;
+static AVFifoBuffer *buffer;
 
-// may only be modified by SDL's playback thread or while it is stopped
-static volatile int read_pos;
-// may only be modified by mplayer's thread
-static volatile int write_pos;
 #ifdef USE_SDL_INTERNAL_MIXER
 static unsigned char volume=SDL_MIX_MAXVOLUME;
 #endif
 
-// may only be called by mplayer's thread
-// return value may change between immediately following two calls,
-// and the real number of free bytes might be larger!
-static int buf_free(void) {
-  int free = read_pos - write_pos - CHUNK_SIZE;
-  if (free < 0) free += BUFFSIZE;
-  return free;
-}
-
-// may only be called by SDL's playback thread
-// return value may change between immediately following two calls,
-// and the real number of buffered bytes might be larger!
-static int buf_used(void) {
-  int used = write_pos - read_pos;
-  if (used < 0) used += BUFFSIZE;
-  return used;
+static int write_buffer(unsigned char* data,int len){
+  int free = BUFFSIZE - av_fifo_size(buffer);
+  if (len > free) len = free;
+  return av_fifo_generic_write(buffer, data, len, NULL);
 }
 
-static int write_buffer(unsigned char* data,int len){
-  int first_len = BUFFSIZE - write_pos;
-  int free = buf_free();
-  if (len > free) len = free;
-  if (first_len > len) first_len = len;
-  // till end of buffer
-  fast_memcpy (&buffer[write_pos], data, first_len);
-  if (len > first_len) { // we have to wrap around
-    // remaining part from beginning of buffer
-    fast_memcpy (buffer, &data[first_len], len - first_len);
-  }
-  write_pos = (write_pos + len) % BUFFSIZE;
-  return len;
+#ifdef USE_SDL_INTERNAL_MIXER
+static void mix_audio(void *dst, void *src, int len) {
+  SDL_MixAudio(dst, src, len, volume);
 }
+#endif
 
 static int read_buffer(unsigned char* data,int len){
-  int first_len = BUFFSIZE - read_pos;
-  int buffered = buf_used();
+  int buffered = av_fifo_size(buffer);
   if (len > buffered) len = buffered;
-  if (first_len > len) first_len = len;
-  // till end of buffer
 #ifdef USE_SDL_INTERNAL_MIXER
-  SDL_MixAudio (data, &buffer[read_pos], first_len, volume);
+  return av_fifo_generic_read(buffer, data, len, mix_audio);
 #else
-  fast_memcpy (data, &buffer[read_pos], first_len);
+  return av_fifo_generic_read(buffer, data, len, NULL);
 #endif
-  if (len > first_len) { // we have to wrap around
-    // remaining part from beginning of buffer
-#ifdef USE_SDL_INTERNAL_MIXER
-    SDL_MixAudio (&data[first_len], buffer, len - first_len, volume);
-#else
-    fast_memcpy (&data[first_len], buffer, len - first_len);
-#endif
-  }
-  read_pos = (read_pos + len) % BUFFSIZE;
-  return len;
 }
 
 // end ring buffer stuff
@@ -175,7 +131,7 @@
 	SDL_AudioSpec aspec, obtained;
 	
 	/* Allocate ring-buffer memory */
-	buffer = (unsigned char *) malloc(BUFFSIZE);
+	buffer = av_fifo_alloc(BUFFSIZE);
 
 	mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_SDL_INFO, rate, (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format));
 
@@ -278,7 +234,6 @@
 	ao_data.buffersize=obtained.size;
 	ao_data.outburst = CHUNK_SIZE;
 	
-	reset();
 	/* unsilence audio, if callback is ready */
 	SDL_PauseAudio(0);
 
@@ -292,6 +247,7 @@
 	  usec_sleep(get_delay() * 1000 * 1000);
 	SDL_CloseAudio();
 	SDL_QuitSubSystem(SDL_INIT_AUDIO);
+	av_fifo_free(buffer);
 }
 
 // stop playing and empty buffers (for seeking/pause)
@@ -301,8 +257,7 @@
 
 	SDL_PauseAudio(1);
 	/* Reset ring-buffer state */
-	read_pos = 0;
-	write_pos = 0;
+	av_fifo_reset(buffer);
 	SDL_PauseAudio(0);
 }
 
@@ -325,7 +280,7 @@
 
 // return: how many bytes can be played without blocking
 static int get_space(void){
-    return buf_free();
+    return BUFFSIZE - av_fifo_size(buffer);
 }
 
 // plays 'len' bytes of 'data'
@@ -352,7 +307,7 @@
 
 // return: delay in seconds between first and last sample in buffer
 static float get_delay(void){
-    int buffered = BUFFSIZE - CHUNK_SIZE - buf_free(); // could be less
+    int buffered = av_fifo_size(buffer); // could be less
     return (float)(buffered + ao_data.buffersize)/(float)ao_data.bps;
 }