changeset 7604:32efb806436e

aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder
author arpi
date Sat, 05 Oct 2002 22:55:45 +0000
parents c89106306f5a
children c3bbe602aff3
files cfg-common.h cfg-mplayer.h libmpcodecs/dec_audio.c libmpcodecs/dec_audio.h libmpdemux/stheader.h mencoder.c mplayer.c
diffstat 7 files changed, 218 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/cfg-common.h	Sat Oct 05 22:54:11 2002 +0000
+++ b/cfg-common.h	Sat Oct 05 22:55:45 2002 +0000
@@ -91,6 +91,7 @@
 	// force video/audio rate:
 	{"fps", &force_fps, CONF_TYPE_FLOAT, CONF_MIN, 0, 0, NULL},
 	{"srate", &force_srate, CONF_TYPE_INT, CONF_RANGE, 1000, 8*48000, NULL},
+	{"channels", &audio_output_channels, CONF_TYPE_INT, CONF_RANGE, 1, 6, NULL},
 
 // ------------------------- codec/vfilter options --------------------
 
@@ -187,6 +188,9 @@
 extern int softzoom;
 extern int flip;
 
+/* from dec_audio, currently used for ac3surround decoder only */
+extern int audio_output_channels;
+
 #ifdef STREAMING
 /* defined in network.c */
 extern char *network_username;
--- a/cfg-mplayer.h	Sat Oct 05 22:54:11 2002 +0000
+++ b/cfg-mplayer.h	Sat Oct 05 22:55:45 2002 +0000
@@ -111,9 +111,6 @@
 /* from libvo/aspect.c */
 extern float monitor_aspect;
 
-/* from dec_audio, currently used for ac3surround decoder only */
-extern int audio_output_channels;
-
 /* Options related to audio out plugins */
 struct config ao_plugin_conf[]={
 	{"list", &ao_plugin_cfg.plugin_list, CONF_TYPE_STRING, 0, 0, 0, NULL},
@@ -173,7 +170,6 @@
 	{"dsp", "Use -ao oss:dsp_path!\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
         {"mixer", &mixer_device, CONF_TYPE_STRING, 0, 0, 0, NULL},
 	{"master", "Option -master has been removed, use -aop list=volume instead.\n", CONF_TYPE_PRINT, 0, 0, 0, NULL},
-	{"channels", &audio_output_channels, CONF_TYPE_INT, CONF_RANGE, 2, 6, NULL},
 	// override audio buffer size (used only by -ao oss, anyway obsolete...)
 	{"abs", &ao_data.buffersize, CONF_TYPE_INT, CONF_MIN, 0, 0, NULL},
 
--- a/libmpcodecs/dec_audio.c	Sat Oct 05 22:54:11 2002 +0000
+++ b/libmpcodecs/dec_audio.c	Sat Oct 05 22:55:45 2002 +0000
@@ -18,6 +18,8 @@
 #include "ad.h"
 #include "../libao2/afmt.h"
 
+#include "../libaf/af.h"
+
 #ifdef USE_FAKE_MONO
 int fakemono=0;
 #endif
@@ -118,6 +120,10 @@
 	sh_audio->samplerate,sh_audio->channels,
 	sh_audio->samplesize*8,sh_audio->sample_format,
         sh_audio->i_bps,sh_audio->o_bps,sh_audio->i_bps*8*0.001);
+
+  sh_audio->a_out_buffer_size=sh_audio->a_buffer_size;
+  sh_audio->a_out_buffer=sh_audio->a_buffer;
+  sh_audio->a_out_buffer_len=sh_audio->a_buffer_len;
   
   return 1;
 }
@@ -210,23 +216,149 @@
 
 void uninit_audio(sh_audio_t *sh_audio)
 {
+    if(sh_audio->afilter){
+	mp_msg(MSGT_DECAUDIO,MSGL_V,"Uninit audio filters...\n");
+	af_uninit(sh_audio->afilter);
+	sh_audio->afilter=NULL;
+    }
     if(sh_audio->inited){
 	mp_msg(MSGT_DECAUDIO,MSGL_V,MSGTR_UninitAudioStr,sh_audio->codec->drv);
 	mpadec->uninit(sh_audio);
 	sh_audio->inited=0;
     }
+    if(sh_audio->a_out_buffer!=sh_audio->a_buffer) free(sh_audio->a_out_buffer);
+    sh_audio->a_out_buffer=NULL;
     if(sh_audio->a_buffer) free(sh_audio->a_buffer);
     sh_audio->a_buffer=NULL;
     if(sh_audio->a_in_buffer) free(sh_audio->a_in_buffer);
     sh_audio->a_in_buffer=NULL;
 }
 
+ /* Init audio filters */
+int init_audio_filters(sh_audio_t *sh_audio, 
+	int in_samplerate, int in_channels, int in_format, int in_bps,
+	int out_samplerate, int out_channels, int out_format, int out_bps,
+	int out_minsize, int out_maxsize){
+  af_stream_t* afs=malloc(sizeof(af_stream_t));
+  memset(afs,0,sizeof(af_stream_t));
+
+  // input format: same as codec's output format:
+  afs->input.rate   = in_samplerate;
+  afs->input.nch    = in_channels;
+  afs->input.format = in_format;
+  afs->input.bps    = in_bps;
+
+  // output format: same as ao driver's input format (if missing, fallback to input)
+  afs->output.rate   = out_samplerate ? out_samplerate : afs->input.rate;
+  afs->output.nch    = out_channels ? out_channels : afs->input.nch;
+  afs->output.format = out_format ? out_format : afs->input.format;
+  afs->output.bps    = out_bps ? out_bps : afs->input.bps;
+
+  // filter config:  
+  afs->cfg.force = 0;
+  afs->cfg.list = NULL;
+  
+  mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Building audio filter chain for %dHz/%dch/%dbit -> %dHz/%dch/%dbit...\n",
+      afs->input.rate,afs->input.nch,afs->input.bps*8,
+      afs->output.rate,afs->output.nch,afs->output.bps*8);
+  
+  // let's autoprobe it!
+  if(0 != af_init(afs)){
+    free(afs);
+    return 0; // failed :(
+  }
+  
+  // allocate the a_out_* buffers:
+  if(out_maxsize<out_minsize) out_maxsize=out_minsize;
+  if(out_maxsize<8192) out_maxsize=MAX_OUTBURST; // not sure this is ok
+
+  sh_audio->a_out_buffer_size=out_maxsize;
+  sh_audio->a_out_buffer=malloc(sh_audio->a_out_buffer_size);
+  memset(sh_audio->a_out_buffer,0,sh_audio->a_out_buffer_size);
+  sh_audio->a_out_buffer_len=0;
+  
+  // ok!
+  sh_audio->afilter=(void*)afs;
+  return 1;
+}
+
 int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
 {
-  if(sh_audio->inited) 
-    return mpadec->decode_audio(sh_audio,buf,minlen,maxlen);
+  int declen;
+  af_data_t  afd;  // filter input
+  af_data_t* pafd; // filter output
+
+  if(!sh_audio->inited) return -1; // no codec
+  if(!sh_audio->afilter){
+      // no filter, just decode:
+      // FIXME: don't drop initial decoded data in a_buffer!
+      return mpadec->decode_audio(sh_audio,buf,minlen,maxlen);
+  }
+  
+//  declen=af_inputlen(sh_audio->afilter,minlen);
+  declen=af_calc_insize_constrained(sh_audio->afilter,minlen,maxlen,
+      sh_audio->a_buffer_size-sh_audio->audio_out_minsize);
+
+  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\ndecaudio: minlen=%d maxlen=%d declen=%d (max=%d)\n",
+      minlen, maxlen, declen, sh_audio->a_buffer_size);
+
+  if(declen<=0) return -1; // error!
+
+  // limit declen to buffer size: - DONE by af_calc_insize_constrained
+//  if(declen>sh_audio->a_buffer_size) declen=sh_audio->a_buffer_size;
+
+  // decode if needed:
+  while(declen>sh_audio->a_buffer_len){
+      int len=declen-sh_audio->a_buffer_len;
+      int maxlen=sh_audio->a_buffer_size-sh_audio->a_buffer_len;
+
+      mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"decaudio: decoding %d bytes, max: %d (%d)\n",
+        len, maxlen, sh_audio->audio_out_minsize);
+
+      if(maxlen<sh_audio->audio_out_minsize) break; // don't overflow buffer!
+      // not enough decoded data waiting, decode 'len' bytes more:
+      len=mpadec->decode_audio(sh_audio,
+          sh_audio->a_buffer+sh_audio->a_buffer_len, len, maxlen);
+      if(len<=0) break; // EOF?
+      sh_audio->a_buffer_len+=len;
+  }
+  if(declen>sh_audio->a_buffer_len)
+    declen=sh_audio->a_buffer_len; // still no enough data (EOF) :(
+
+  // round to whole samples:
+//  declen/=sh_audio->samplesize*sh_audio->channels;
+//  declen*=sh_audio->samplesize*sh_audio->channels;
+
+  // run the filters:
+  afd.audio=sh_audio->a_buffer;
+  afd.len=declen;
+  afd.rate=sh_audio->samplerate;
+  afd.nch=sh_audio->channels;
+  afd.format=sh_audio->sample_format;
+  afd.bps=sh_audio->samplesize;
+  //pafd=&afd;
+//  printf("\nAF: %d --> ",declen);
+  pafd=af_play(sh_audio->afilter,&afd);
+//  printf("%d  \n",pafd->len);
+
+  if(!pafd) return -1; // error
+
+  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"decaudio: declen=%d out=%d (max %d)\n",
+      declen, pafd->len, maxlen);
+  
+  // copy filter==>out:
+  if(maxlen < pafd->len)
+    mp_msg(MSGT_DECAUDIO,MSGL_WARN,"%i bytes of audio data lost due to buffer overflow, len = %i", pafd->len - maxlen,pafd->len);
   else
-    return -1;
+    maxlen=pafd->len;
+  memmove(buf, pafd->audio, maxlen);
+  
+  // remove processed data from decoder buffer:
+  sh_audio->a_buffer_len-=declen;
+  if(sh_audio->a_buffer_len>0)
+    memmove(sh_audio->a_buffer, sh_audio->a_buffer+declen, sh_audio->a_buffer_len);
+  
+  return maxlen;
 }
 
 void resync_audio_stream(sh_audio_t *sh_audio)
--- a/libmpcodecs/dec_audio.h	Sat Oct 05 22:54:11 2002 +0000
+++ b/libmpcodecs/dec_audio.h	Sat Oct 05 22:55:45 2002 +0000
@@ -9,3 +9,8 @@
 extern void resync_audio_stream(sh_audio_t *sh_audio);
 extern void skip_audio_frame(sh_audio_t *sh_audio);
 extern void uninit_audio(sh_audio_t *sh_audio);
+
+extern int init_audio_filters(sh_audio_t *sh_audio, 
+	int in_samplerate, int in_channels, int in_format, int in_bps,
+	int out_samplerate, int out_channels, int out_format, int out_bps,
+	int out_minsize, int out_maxsize);
\ No newline at end of file
--- a/libmpdemux/stheader.h	Sat Oct 05 22:54:11 2002 +0000
+++ b/libmpdemux/stheader.h	Sat Oct 05 22:55:45 2002 +0000
@@ -55,15 +55,21 @@
   int o_bps; // == samplerate*samplesize*channels   (uncompr. bytes/sec)
   int i_bps; // == bitrate  (compressed bytes/sec)
   // in buffers:
-  int audio_in_minsize;
+  int audio_in_minsize;	// max. compressed packet size (== min. in buffer size)
   char* a_in_buffer;
   int a_in_buffer_len;
   int a_in_buffer_size;
-  // out buffers:
-  int audio_out_minsize;
+  // decoder buffers:
+  int audio_out_minsize; // max. uncompressed packet size (==min. out buffsize)
   char* a_buffer;
   int a_buffer_len;
   int a_buffer_size;
+  // output buffers:
+  char* a_out_buffer;
+  int a_out_buffer_len;
+  int a_out_buffer_size;
+//  void* audio_out;        // the audio_out handle, used for this audio stream
+  void* afilter;          // the audio filter stream
   // win32-compatible codec parameters:
   AVIStreamHeader audio;
   WAVEFORMATEX* wf;
--- a/mencoder.c	Sat Oct 05 22:54:11 2002 +0000
+++ b/mencoder.c	Sat Oct 05 22:55:45 2002 +0000
@@ -45,6 +45,8 @@
 
 #include "libvo/video_out.h"
 
+#include "libao2/afmt.h"
+
 #include "libmpcodecs/mp_image.h"
 #include "libmpcodecs/dec_audio.h"
 #include "libmpcodecs/dec_video.h"
@@ -249,19 +251,19 @@
     while(size<total && !at_eof){
 	int len=total-size;
 		if(len>MAX_OUTBURST) len=MAX_OUTBURST;
-		if(len>sh_audio->a_buffer_size) len=sh_audio->a_buffer_size;
-		if(len>sh_audio->a_buffer_len){
+		if(len>sh_audio->a_out_buffer_size) len=sh_audio->a_out_buffer_size;
+		if(len>sh_audio->a_out_buffer_len){
 		    int ret=decode_audio(sh_audio,
-			&sh_audio->a_buffer[sh_audio->a_buffer_len],
-    			len-sh_audio->a_buffer_len,
-			sh_audio->a_buffer_size-sh_audio->a_buffer_len);
-		    if(ret>0) sh_audio->a_buffer_len+=ret; else at_eof=1;
+			&sh_audio->a_out_buffer[sh_audio->a_out_buffer_len],
+    			len-sh_audio->a_out_buffer_len,
+			sh_audio->a_out_buffer_size-sh_audio->a_out_buffer_len);
+		    if(ret>0) sh_audio->a_out_buffer_len+=ret; else at_eof=1;
 		}
-		if(len>sh_audio->a_buffer_len) len=sh_audio->a_buffer_len;
-		memcpy(buffer+size,sh_audio->a_buffer,len);
-		sh_audio->a_buffer_len-=len; size+=len;
-		if(sh_audio->a_buffer_len>0)
-		    memcpy(sh_audio->a_buffer,&sh_audio->a_buffer[len],sh_audio->a_buffer_len);
+		if(len>sh_audio->a_out_buffer_len) len=sh_audio->a_out_buffer_len;
+		memcpy(buffer+size,sh_audio->a_out_buffer,len);
+		sh_audio->a_out_buffer_len-=len; size+=len;
+		if(sh_audio->a_out_buffer_len>0)
+		    memcpy(sh_audio->a_out_buffer,&sh_audio->a_out_buffer[len],sh_audio->a_out_buffer_len);
     }
     return size;
 }
@@ -694,15 +696,25 @@
     printf("CBR PCM audio selected\n");
     mux_a->h.dwSampleSize=2*sh_audio->channels;
     mux_a->h.dwScale=1;
-    mux_a->h.dwRate=sh_audio->samplerate;
+    mux_a->h.dwRate=force_srate?force_srate:sh_audio->samplerate;
     mux_a->wf=malloc(sizeof(WAVEFORMATEX));
     mux_a->wf->nBlockAlign=mux_a->h.dwSampleSize;
     mux_a->wf->wFormatTag=0x1; // PCM
-    mux_a->wf->nChannels=sh_audio->channels;
-    mux_a->wf->nSamplesPerSec=sh_audio->samplerate;
+    mux_a->wf->nChannels=audio_output_channels?audio_output_channels:sh_audio->channels;
+    mux_a->wf->nSamplesPerSec=mux_a->h.dwRate;
     mux_a->wf->nAvgBytesPerSec=mux_a->h.dwSampleSize*mux_a->wf->nSamplesPerSec;
     mux_a->wf->wBitsPerSample=16;
     mux_a->wf->cbSize=0; // FIXME for l3codeca.acm
+    // setup filter:
+    if(!init_audio_filters(sh_audio, 
+        sh_audio->samplerate,
+	sh_audio->channels, sh_audio->sample_format, sh_audio->samplesize,
+	mux_a->wf->nSamplesPerSec, mux_a->wf->nChannels,
+	(mux_a->wf->wBitsPerSample==8)?	AFMT_U8:AFMT_S16_LE,
+	mux_a->wf->wBitsPerSample/8,
+	16384, mux_a->wf->nAvgBytesPerSec)){
+      mp_msg(MSGT_CPLAYER,MSGL_ERR,"Couldn't find matching filter / ao format!\n");
+    }
     break;
 case ACODEC_VBRMP3:
     printf("MP3 audio selected\n");
@@ -712,8 +724,9 @@
     if(sizeof(MPEGLAYER3WAVEFORMAT)!=30) mp_msg(MSGT_MENCODER,MSGL_WARN,"sizeof(MPEGLAYER3WAVEFORMAT)==%d!=30, maybe broken C compiler?\n",sizeof(MPEGLAYER3WAVEFORMAT));
     mux_a->wf=malloc(sizeof(MPEGLAYER3WAVEFORMAT)); // should be 30
     mux_a->wf->wFormatTag=0x55; // MP3
-    mux_a->wf->nChannels= sh_audio->channels;
-    mux_a->wf->nSamplesPerSec=force_srate?force_srate:sh_audio->samplerate;
+    mux_a->wf->nChannels= (lame_param_mode<0) ? sh_audio->channels :
+	((lame_param_mode==3) ? 1 : 2);
+    mux_a->wf->nSamplesPerSec=mux_a->h.dwRate;
     mux_a->wf->nAvgBytesPerSec=192000/8; // FIXME!
     mux_a->wf->nBlockAlign=(mux_a->h.dwRate<32000)?576:1152; // required for l3codeca.acm + WMP 6.4
     mux_a->wf->wBitsPerSample=0; //16;
@@ -724,6 +737,15 @@
     ((MPEGLAYER3WAVEFORMAT*)(mux_a->wf))->nBlockSize=(mux_a->h.dwRate<32000)?576:1152; // ???
     ((MPEGLAYER3WAVEFORMAT*)(mux_a->wf))->nFramesPerBlock=1;
     ((MPEGLAYER3WAVEFORMAT*)(mux_a->wf))->nCodecDelay=0;
+    // setup filter:
+    if(!init_audio_filters(sh_audio, 
+        sh_audio->samplerate,
+	sh_audio->channels, sh_audio->sample_format, sh_audio->samplesize,
+	mux_a->wf->nSamplesPerSec, mux_a->wf->nChannels,
+	AFMT_S16_LE, 2,
+	4608, mux_a->h.dwRate*mux_a->wf->nChannels*2)){
+      mp_msg(MSGT_CPLAYER,MSGL_ERR,"Couldn't find matching filter / ao format!\n");
+    }
     break;
 }
 
@@ -748,7 +770,8 @@
 
 lame=lame_init();
 lame_set_bWriteVbrTag(lame,0);
-lame_set_in_samplerate(lame,sh_audio->samplerate);
+lame_set_in_samplerate(lame,mux_a->wf->nSamplesPerSec);
+//lame_set_in_samplerate(lame,sh_audio->samplerate); // if resampling done by lame
 lame_set_num_channels(lame,mux_a->wf->nChannels);
 lame_set_out_samplerate(lame,mux_a->wf->nSamplesPerSec);
 lame_set_quality(lame,lame_param_algqual); // 0 = best q
--- a/mplayer.c	Sat Oct 05 22:54:11 2002 +0000
+++ b/mplayer.c	Sat Oct 05 22:55:45 2002 +0000
@@ -1237,6 +1237,7 @@
   if(!(audio_out=init_best_audio_out(audio_driver_list,
       (ao_plugin_cfg.plugin_list), // plugin flag
       force_srate?force_srate:sh_audio->samplerate,
+      audio_output_channels?audio_output_channels:
       sh_audio->channels,sh_audio->sample_format,0))){
     // FAILED:
     mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CannotInitAO);
@@ -1244,7 +1245,7 @@
   } else {
     // SUCCESS:
     inited_flags|=INITED_AO;
-    mp_msg(MSGT_CPLAYER,MSGL_INFO,"AO: [%s] %iHz %dch %s\n",
+    mp_msg(MSGT_CPLAYER,MSGL_INFO,"AO: [%s] %dHz %dch %s\n",
       audio_out->info->short_name,
       force_srate?force_srate:sh_audio->samplerate,
       sh_audio->channels,
@@ -1253,6 +1254,19 @@
       audio_out->info->name, audio_out->info->author);
     if(strlen(audio_out->info->comment) > 0)
       mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_AOComment, audio_out->info->comment);
+    // init audio filters:
+#if 1
+    current_module="af_init";
+    if(!init_audio_filters(sh_audio, 
+        sh_audio->samplerate,
+	sh_audio->channels, sh_audio->sample_format, sh_audio->samplesize,
+	ao_data.samplerate, ao_data.channels, ao_data.format,
+	audio_out_format_bits(ao_data.format)/8, /* ao_data.bps, */
+	ao_data.outburst*4, ao_data.buffersize)){
+      mp_msg(MSGT_CPLAYER,MSGL_ERR,"Couldn't find matching filter / ao format, -> nosound\n");
+      sh_audio=d_audio->sh=NULL; // -> nosound
+    }
+#endif
   }
 }
 
@@ -1338,24 +1352,25 @@
   // Fill buffer if needed:
   current_module="decode_audio";   // Enter AUDIO decoder module
   t=GetTimer();
-  while(sh_audio->a_buffer_len<playsize && !d_audio->eof){
-    int ret=decode_audio(sh_audio,&sh_audio->a_buffer[sh_audio->a_buffer_len],
-        playsize-sh_audio->a_buffer_len,sh_audio->a_buffer_size-sh_audio->a_buffer_len);
+  while(sh_audio->a_out_buffer_len<playsize && !d_audio->eof){
+    int ret=decode_audio(sh_audio,&sh_audio->a_out_buffer[sh_audio->a_out_buffer_len],
+        playsize-sh_audio->a_out_buffer_len,sh_audio->a_out_buffer_size-sh_audio->a_out_buffer_len);
     if(ret<=0) break; // EOF?
-    sh_audio->a_buffer_len+=ret;
+    sh_audio->a_out_buffer_len+=ret;
   }
   t=GetTimer()-t;
   tt = t*0.000001f; audio_time_usage+=tt;
-  if(playsize>sh_audio->a_buffer_len) playsize=sh_audio->a_buffer_len;
+  if(playsize>sh_audio->a_out_buffer_len) playsize=sh_audio->a_out_buffer_len;
 
   // play audio:  
   current_module="play_audio";
-  playsize=audio_out->play(sh_audio->a_buffer,playsize,0);
+  playsize=audio_out->play(sh_audio->a_out_buffer,playsize,0);
 
   if(playsize>0){
-      sh_audio->a_buffer_len-=playsize;
-      memmove(sh_audio->a_buffer,&sh_audio->a_buffer[playsize],sh_audio->a_buffer_len);
-      sh_audio->timer+=playsize/(float)(sh_audio->o_bps);
+      sh_audio->a_out_buffer_len-=playsize;
+      memmove(sh_audio->a_out_buffer,&sh_audio->a_out_buffer[playsize],sh_audio->a_out_buffer_len);
+      sh_audio->timer+=playsize/((float)((ao_data.bps && sh_audio->afilter) ?
+          ao_data.bps : sh_audio->o_bps));
   }
 
   break;