changeset 4313:1dbffed555a6

Added buffering of output data
author anders
date Wed, 23 Jan 2002 12:28:36 +0000
parents 971836f677a9
children 7fae2ec7c968
files libao2/ao_plugin.c
diffstat 1 files changed, 51 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/libao2/ao_plugin.c	Wed Jan 23 08:50:30 2002 +0000
+++ b/libao2/ao_plugin.c	Wed Jan 23 12:28:36 2002 +0000
@@ -25,16 +25,19 @@
 // local data 
 typedef struct ao_plugin_local_data_s
 {
-  ao_functions_t* driver;      // Output driver set in mplayer.c
+  void* buf;					 // Output data buffer
+  int len;					 // Amount of data in buffer
+  float bps;					 // Bytes per second out
+  ao_functions_t* driver;      			 // Output driver
   ao_plugin_functions_t** plugins;               // List of used plugins
   ao_plugin_functions_t* available_plugins[NPL]; // List of available plugins
 } ao_plugin_local_data_t;
 
-static ao_plugin_local_data_t ao_plugin_local_data={NULL,NULL,AO_PLUGINS};
+static ao_plugin_local_data_t ao_plugin_local_data={NULL,0,0.0,NULL,NULL,AO_PLUGINS};
 
-// gloabal data 
-volatile ao_plugin_data_t ao_plugin_data; // data used by the plugins
-volatile ao_plugin_cfg_t  ao_plugin_cfg=CFG_DEFAULTS;  // cfg data set in cfg-mplayer.h
+// global data 
+volatile ao_plugin_data_t ao_plugin_data; // Data used by the plugins
+volatile ao_plugin_cfg_t  ao_plugin_cfg=CFG_DEFAULTS; // Set in cfg-mplayer.h
 
 // to set/get/query special features/parameters
 static int control(int cmd,int arg){
@@ -102,7 +105,7 @@
 static int init(int rate,int channels,int format,int flags){
   int ok=1;
 
-  /* Create list of plugins from cfg option */
+  // Create list of plugins from cfg option
   int i=0; 
   if(ao_plugin_cfg.plugin_list){
     if(!add_plugin(i,ao_plugin_cfg.plugin_list))
@@ -124,6 +127,20 @@
   
   if(!ok) return 0;
 
+  // Calculate bps
+  ao_plugin_local_data.bps=(float)(ao_plugin_data.rate * 
+				   ao_plugin_data.channels);
+
+  if(ao_plugin_data.format == AFMT_S16_LE ||
+     ao_plugin_data.format == AFMT_S16_BE ||
+     ao_plugin_data.format == AFMT_U16_LE ||
+     ao_plugin_data.format == AFMT_U16_BE)
+    ao_plugin_local_data.bps *= 2;
+
+  if(ao_plugin_data.format == AFMT_S32_LE ||
+     ao_plugin_data.format == AFMT_S32_BE)
+    ao_plugin_local_data.bps *= 4;
+
   // This should never happen but check anyway 
   if(NULL==ao_plugin_local_data.driver)
     return 0;
@@ -142,6 +159,13 @@
 
   if(!ok) return 0;
 
+  // Allocate output buffer */
+  if(ao_plugin_local_data.buf)
+    free(ao_plugin_local_data.buf);
+  ao_plugin_local_data.buf=malloc(MAX_OUTBURST);
+
+  if(!ao_plugin_local_data.buf) return 0;
+
   return 1;
 }
 
@@ -153,6 +177,8 @@
     plugin(i++)->uninit();
   if(ao_plugin_local_data.plugins)
     free(ao_plugin_local_data.plugins);
+  if(ao_plugin_local_data.buf)
+    free(ao_plugin_local_data.buf);
 }
 
 // stop playing and empty buffers (for seeking/pause)
@@ -161,6 +187,7 @@
   driver()->reset();
   while(plugin(i))
     plugin(i++)->reset();
+  ao_plugin_local_data.len=0;
 }
 
 // stop playing, keep buffers (for pause)
@@ -176,6 +203,8 @@
 // return: how many bytes can be played without blocking
 static int get_space(){
   double sz=(double)(driver()->get_space());
+  if(sz+(double)ao_plugin_local_data.len > (double)MAX_OUTBURST)
+    sz=(double)MAX_OUTBURST-(double)ao_plugin_local_data.len;
   sz*=ao_plugin_data.sz_mult;
   sz+=ao_plugin_data.sz_fix;
   return (int)(sz);
@@ -184,22 +213,25 @@
 // plays 'len' bytes of 'data'
 // return: number of bytes played
 static int play(void* data,int len,int flags){
-  int i=0;
-  /* Due to constant buffer sizes in plugins limit length */
-  int tmp = get_space();
+  int l,i=0;
+  // Limit length to avoid over flow in plugins
+  int tmp = driver()->get_space();
   int ret_len =(tmp<len)?tmp:len;
-  /* Filter data */
-  ao_plugin_data.len=ret_len;  
+  // Filter data
+  ao_plugin_data.len=ret_len;
   ao_plugin_data.data=data;
   while(plugin(i))
     plugin(i++)->play();
-  /* Send data to output */
-  //fprintf(stderr, "ao_plugin: ret_len=%d, len=%d\n", ret_len, len);
-  len=driver()->play(ao_plugin_data.data,ao_plugin_data.len,flags);
-  //fprintf(stderr, "ao_plugin: returned len=%d\n", len);
-
-  if(len!=ao_plugin_data.len)
-    fprintf(stderr,"[ao_plugin] Warning under or over flow in sound plugin\n");
+  // Copy data to output buffer
+  memcpy(ao_plugin_local_data.buf+ao_plugin_local_data.len,
+	 ao_plugin_data.data,ao_plugin_data.len);
+  // Send data to output
+  l=driver()->play(ao_plugin_local_data.buf,
+		   ao_plugin_data.len+ao_plugin_local_data.len,flags);
+  // Save away unsent data
+  ao_plugin_local_data.len=ao_plugin_data.len+ao_plugin_local_data.len-l;
+  memcpy(ao_plugin_local_data.buf,ao_plugin_local_data.buf+l,
+	 ao_plugin_local_data.len);
   
   return ret_len;
 }
@@ -207,6 +239,7 @@
 // return: delay in seconds between first and last sample in buffer
 static float get_delay(){
   float delay=driver()->get_delay();
+  delay+=(float)ao_plugin_local_data.len/ao_plugin_local_data.bps;
   delay*=ao_plugin_data.delay_mult;
   delay+=ao_plugin_data.delay_fix;
   return delay;