aufio filter layer (libaf) integration to libmpcodecs, mplayer and mencoder

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7605 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi 2002-10-05 22:55:45 +00:00
parent 18e342e06c
commit 3053a8b7f2
7 changed files with 218 additions and 37 deletions

View File

@ -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 float movie_aspect;
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;

View File

@ -111,9 +111,6 @@ extern int nortc;
/* 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 @@ static config_t mplayer_opts[]={
{"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},

View File

@ -18,6 +18,8 @@ extern int verbose; // defined in mplayer.c
#include "ad.h"
#include "../libao2/afmt.h"
#include "../libaf/af.h"
#ifdef USE_FAKE_MONO
int fakemono=0;
#endif
@ -118,6 +120,10 @@ int init_audio_codec(sh_audio_t *sh_audio)
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 @@ return 1; // success
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)

View File

@ -9,3 +9,8 @@ extern int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int m
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);

View File

@ -55,15 +55,21 @@ typedef struct {
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;

View File

@ -45,6 +45,8 @@ static char* banner_text=
#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 @@ static int dec_audio(sh_audio_t *sh_audio,unsigned char* buffer,int total){
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 @@ case ACODEC_PCM:
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 @@ case ACODEC_VBRMP3:
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 @@ case ACODEC_VBRMP3:
((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 @@ case ACODEC_VBRMP3:
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

View File

@ -1237,6 +1237,7 @@ if(sh_audio){
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 @@ if(sh_audio){
} 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 @@ if(sh_audio){
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 @@ while(sh_audio){
// 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;