[MPlayer-dev-eng] New audio filter layer finished

Arpi arpi at thot.banki.hu
Wed Oct 2 03:50:43 CEST 2002


Hi,

> > > put the code in dec_audio. I will have another look at it and send a
> > > new patch. If anyone familiar with the code can come up with a better
> > > solution please send a patch.
> > i'll work on this, hopefully today but more probably only tomorrow.
> > i've the code in my mind, just needs to be organized and typed ;)
> 
> Thanks!

Ok i did it, here comes the patch, for testing.
NOTE: mencoder is not changed yet, it won't work with this patch applied! i'll fix it tomorrow.

I've changed teh path a little bit: added a new func to setup filters,
so the init order now:

1. find & init audio codec
2. find & init ao driver
3. find & init filters, to convert from codec's out format to ao's input format

this way i don't even have to pass channels/srate to the filter layer, and
it will auto-fix stereo-only soundcards and audio format incompatibilities
(assuming that teh ao driver set up ao_data.* fields according to the actual
output format, even if it differs from the requested one - works with OSS.)

so, in short: user forces srate/channels/etc, it's passed to teh ao driver.
teh ao driver does something with it, maybe ignore if it can't support that.
so, ao set up somehting and set ao_data.* fields to reflect that.
then teh filter layer will do the conversion from teh codec format to teh ao
one.

ok it wasn't shorter :)
but i hope you got it.

now, the problems.
i've tried to play the matrix 1 trailer .vob (2.0ch 48khz ac3) wiht -srate
44100 and i got strange noise, clicks sometimes.
with an avi with mp3 audio i didn't get such thing.

but what's more important: it seems the resample filter delays 1.2-1.5
seconds of teh audio. the a-v sync code detects and slowly corrects it
but it took a while.  is there any partcular reason for such big delay?

ok, here comes my version then:

Index: mplayer.c
===================================================================
RCS file: /cvsroot/mplayer/main/mplayer.c,v
retrieving revision 1.584
diff -u -r1.584 mplayer.c
--- mplayer.c	1 Oct 2002 22:29:03 -0000	1.584
+++ mplayer.c	2 Oct 2002 01:41:08 -0000
@@ -1255,6 +1255,14 @@
       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(!init_audio_filters(sh_audio, 
+	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
+    }
   }
 }
 
@@ -1340,24 +1348,24 @@
   // 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 ? ao_data.bps : sh_audio->o_bps);
   }
 
   break;
Index: libmpcodecs/dec_audio.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/dec_audio.c,v
retrieving revision 1.13
diff -u -r1.13 dec_audio.c
--- libmpcodecs/dec_audio.c	29 Sep 2002 21:52:10 -0000	1.13
+++ libmpcodecs/dec_audio.c	2 Oct 2002 01:41:09 -0000
@@ -18,6 +18,8 @@
 #include "ad.h"
 #include "../libao2/afmt.h"
 
+#include "../libaf/af.h"
+
 #ifdef USE_FAKE_MONO
 int fakemono=0;
 #endif
@@ -221,12 +223,115 @@
     sh_audio->a_in_buffer=NULL;
 }
 
+ /* Init audio filters */
+int init_audio_filters(sh_audio_t *sh_audio, 
+	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   = sh_audio->samplerate;
+  afs->input.nch    = sh_audio->channels;
+  afs->input.format = sh_audio->sample_format;
+  afs->input.bps    = sh_audio->samplesize;
+
+  // 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);
+
+  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"decaudio: minlen=%d maxlen=%d declen=%d (max=%d)\n",
+      minlen, maxlen, declen, sh_audio->a_buffer_size);
+
+  // limit declen to buffer size:
+  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 :(
+
+  // 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;
+  pafd=af_play(sh_audio->afilter,&afd);
+  
+  // 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)
Index: libmpcodecs/dec_audio.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpcodecs/dec_audio.h,v
retrieving revision 1.5
diff -u -r1.5 dec_audio.h
--- libmpcodecs/dec_audio.h	28 Sep 2002 02:23:20 -0000	1.5
+++ libmpcodecs/dec_audio.h	2 Oct 2002 01:41:09 -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 out_samplerate, int out_channels, int out_format, int out_bps,
+	int out_minsize, int out_maxsize);
+
Index: libmpdemux/stheader.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/stheader.h,v
retrieving revision 1.33
diff -u -r1.33 stheader.h
--- libmpdemux/stheader.h	22 Sep 2002 00:43:14 -0000	1.33
+++ libmpdemux/stheader.h	2 Oct 2002 01:41:09 -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'rpi / Astral & ESP-team

--
Developer of MPlayer, the Movie Player for Linux - http://www.MPlayerHQ.hu



More information about the MPlayer-dev-eng mailing list