# HG changeset patch # User anders # Date 1033476810 0 # Node ID 8819fdf88b5d9c2340063adcb5f078bef251c795 # Parent a0bba1b6c458d281661c79174f464623c90ba6a4 Adding support for multiple audio streams and removing annoying message from resample and format diff -r a0bba1b6c458 -r 8819fdf88b5d libaf/af.c --- a/libaf/af.c Tue Oct 01 09:20:27 2002 +0000 +++ b/libaf/af.c Tue Oct 01 12:53:30 2002 +0000 @@ -27,28 +27,6 @@ NULL \ }; -// Command line config switches -af_cfg_t af_cfg={\ - 0,\ - 0,\ - 0,\ - 0,\ - NULL,\ -}; - - -// Initialization types -#define SLOW 1 -#define FAST 2 -#define FORCE 3 - -// The first and last filter in the list -static af_instance_t* first=NULL; -static af_instance_t* last=NULL; -// Storage for input and output data formats (set by init) -static af_data_t input; -static af_data_t output; - /* Find a filter in the static list of filters using it's name. This function is used internally */ af_info_t* af_find(char*name) @@ -89,9 +67,9 @@ /* Create and insert a new filter of type name before the filter in the argument. This function can be called during runtime, the return value is the new filter */ -af_instance_t* af_prepend(af_instance_t* af, char* name) +af_instance_t* af_prepend(af_stream_t* s, af_instance_t* af, char* name) { - // Create the new filter and make sure it is ok + // Create the new filter and make sure it is OK af_instance_t* new=af_create(name); if(!new) return NULL; @@ -102,18 +80,18 @@ af->prev=new; } else - last=new; + s->last=new; if(new->prev) new->prev->next=new; else - first=new; + s->first=new; return new; } /* Create and insert a new filter of type name after the filter in the argument. This function can be called during runtime, the return value is the new filter */ -af_instance_t* af_append(af_instance_t* af, char* name) +af_instance_t* af_append(af_stream_t* s, af_instance_t* af, char* name) { // Create the new filter and make sure it is OK af_instance_t* new=af_create(name); @@ -126,16 +104,16 @@ af->next=new; } else - first=new; + s->first=new; if(new->next) new->next->prev=new; else - last=new; + s->last=new; return new; } // Uninit and remove the filter "af" -void af_remove(af_instance_t* af) +void af_remove(af_stream_t* s, af_instance_t* af) { if(!af) return; @@ -143,11 +121,11 @@ if(af->prev) af->prev->next=af->next; else - first=af->next; + s->first=af->next; if(af->next) af->next->prev=af->prev; else - last=af->prev; + s->last=af->prev; // Uninitialize af and free memory af->uninit(af); @@ -155,7 +133,7 @@ } /* Reinitializes all filters downstream from the filter given in the argument */ -int af_reinit(af_instance_t* af) +int af_reinit(af_stream_t* s, af_instance_t* af) { if(!af) return AF_ERROR; @@ -166,7 +144,7 @@ // Check if this is the first filter if(!af->prev) - memcpy(&in,&input,sizeof(af_data_t)); + memcpy(&in,&(s->input),sizeof(af_data_t)); else memcpy(&in,af->prev->data,sizeof(af_data_t)); // Reset just in case... @@ -180,33 +158,33 @@ case AF_FALSE:{ // Configuration filter is needed af_instance_t* new = NULL; // Insert channels filter - if((af->prev?af->prev->data->nch:input.nch) != in.nch){ + if((af->prev?af->prev->data->nch:s->input.nch) != in.nch){ // Create channels filter - if(NULL == (new = af_prepend(af,"channels"))) + if(NULL == (new = af_prepend(s,af,"channels"))) return AF_ERROR; // Set number of output channels if(AF_OK != (rv = new->control(new,AF_CONTROL_CHANNELS,&in.nch))) return rv; // Initialize channels filter if(!new->prev) - memcpy(&in,&input,sizeof(af_data_t)); + memcpy(&in,&(s->input),sizeof(af_data_t)); else memcpy(&in,new->prev->data,sizeof(af_data_t)); if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in))) return rv; } // Insert format filter - if(((af->prev?af->prev->data->format:input.format) != in.format) || - ((af->prev?af->prev->data->bps:input.bps) != in.bps)){ + if(((af->prev?af->prev->data->format:s->input.format) != in.format) || + ((af->prev?af->prev->data->bps:s->input.bps) != in.bps)){ // Create format filter - if(NULL == (new = af_prepend(af,"format"))) + if(NULL == (new = af_prepend(s,af,"format"))) return AF_ERROR; // Set output format if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in))) return rv; // Initialize format filter if(!new->prev) - memcpy(&in,&input,sizeof(af_data_t)); + memcpy(&in,&(s->input),sizeof(af_data_t)); else memcpy(&in,new->prev->data,sizeof(af_data_t)); if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in))) @@ -219,15 +197,15 @@ } case AF_DETACH:{ // Filter is redundant and wants to be unloaded af_instance_t* aft=af->prev; - af_remove(af); + af_remove(s,af); if(aft) af=aft; else - af=first; // Restart configuration + af=s->first; // Restart configuration break; } default: - mp_msg(MSGT_AFILTER,MSGL_ERR,"Reinit did not work, audio filter '%s' returned error code %i\n",af->info->name,rv); + mp_msg(MSGT_AFILTER,MSGL_ERR,"Reinitialization did not work, audio filter '%s' returned error code %i\n",af->info->name,rv); return AF_ERROR; } af=af->next; @@ -237,9 +215,9 @@ /* Find filter in the dynamic filter list using it's name This function is used for finding already initialized filters */ -af_instance_t* af_get(char* name) +af_instance_t* af_get(af_stream_t* s, char* name) { - af_instance_t* af=first; + af_instance_t* af=s->first; while(af->next != NULL){ if(!strcmp(af->info->name,name)) return af; @@ -249,27 +227,34 @@ } // Uninit and remove all filters -void af_uninit() +void af_uninit(af_stream_t* s) { - while(first) - af_remove(first); + while(s->first) + af_remove(s,s->first); } -/* Init read configuration and create filter list accordingly. In and - out contains the format of the current movie and the formate of the - preferred output respectively */ -int af_init(af_data_t* in, af_data_t* out) +/* Initialize the stream "s". This function creates a new filter list + if necessary according to the values set in input and output. Input + and output should contain the format of the current movie and the + formate of the preferred output respectively. The function is + reentrant i.e. if called with an already initialized stream the + stream will be reinitialized. The return value is 0 if success and + -1 if failure */ +int af_init(af_stream_t* s) { int cfg=SLOW; // configuration type int i=0; + // Sanity check + if(!s) return -1; + // Precaution in case caller is misbehaving - in->audio = out->audio = NULL; - in->len = out->len = 0; + s->input.audio = s->output.audio = NULL; + s->input.len = s->output.len = 0; // Figure out how fast the machine is - if(af_cfg.force) - cfg=af_cfg.force; + if(s->cfg.force) + cfg=s->cfg.force; else{ # if defined(HAVE_SSE) || defined(HAVE_3DNOWEX) cfg=FAST; @@ -277,92 +262,91 @@ cfg=SLOW; # endif } - - // Input and output configuration - memcpy(&input,in,sizeof(af_data_t)); - memcpy(&output,out,sizeof(af_data_t)); // Check if this is the first call - if(!first){ + if(!s->first){ // Add all filters in the list (if there are any) - if(!af_cfg.list){ - if(!af_append(first,"dummy")) // To make automatic format conversion work + if(!s->cfg.list){ // To make automatic format conversion work + if(!af_append(s,s->first,"dummy")) return -1; } else{ - while(af_cfg.list[i]){ - if(!af_append(last,af_cfg.list[i++])) + while(s->cfg.list[i]){ + if(!af_append(s,s->last,s->cfg.list[i++])) return -1; } } } // Init filters - if(AF_OK != af_reinit(first)) + if(AF_OK != af_reinit(s,s->first)) return -1; // Check output format if(cfg!=FORCE){ af_instance_t* af = NULL; // New filter // Check output frequency if not OK fix with resample - if(last->data->rate!=output.rate){ - if(NULL==(af=af_get("resample"))){ + if(s->last->data->rate!=s->output.rate){ + if(NULL==(af=af_get(s,"resample"))){ if(cfg==SLOW){ - if(!strcmp(first->info->name,"format")) - af = af_append(first,"resample"); + if(!strcmp(s->first->info->name,"format")) + af = af_append(s,s->first,"resample"); else - af = af_prepend(first,"resample"); + af = af_prepend(s,s->first,"resample"); } else{ - if(!strcmp(last->info->name,"format")) - af = af_prepend(last,"resample"); + if(!strcmp(s->last->info->name,"format")) + af = af_prepend(s,s->last,"resample"); else - af = af_append(last,"resample"); + af = af_append(s,s->last,"resample"); } } // Init the new filter - if(!af || (AF_OK != af->control(af,AF_CONTROL_RESAMPLE,&output.rate))) + if(!af || (AF_OK != af->control(af,AF_CONTROL_RESAMPLE,&(s->output.rate)))) return -1; - if(AF_OK != af_reinit(af)) + if(AF_OK != af_reinit(s,af)) return -1; } // Check number of output channels fix if not OK // If needed always inserted last -> easy to screw up other filters - if(last->data->nch!=output.nch){ - if(!strcmp(last->info->name,"format")) - af = af_prepend(last,"channels"); + if(s->last->data->nch!=s->output.nch){ + if(!strcmp(s->last->info->name,"format")) + af = af_prepend(s,s->last,"channels"); else - af = af_append(last,"channels"); + af = af_append(s,s->last,"channels"); // Init the new filter - if(!af || (AF_OK != af->control(af,AF_CONTROL_CHANNELS,&output.nch))) + if(!af || (AF_OK != af->control(af,AF_CONTROL_CHANNELS,&(s->output.nch)))) return -1; - if(AF_OK != af_reinit(af)) + if(AF_OK != af_reinit(s,af)) return -1; } // Check output format fix if not OK - if((last->data->format != output.format) || (last->data->bps != output.bps)){ - if(strcmp(last->info->name,"format")) - af = af_append(last,"format"); + if((s->last->data->format != s->output.format) || + (s->last->data->bps != s->output.bps)){ + if(strcmp(s->last->info->name,"format")) + af = af_append(s,s->last,"format"); else - af = last; + af = s->last; // Init the new filter - if(!af ||(AF_OK != af->control(af,AF_CONTROL_FORMAT,&output))) + if(!af ||(AF_OK != af->control(af,AF_CONTROL_FORMAT,&(s->output)))) return -1; - if(AF_OK != af_reinit(af)) + if(AF_OK != af_reinit(s,af)) return -1; } // Re init again just in case - if(AF_OK != af_reinit(first)) + if(AF_OK != af_reinit(s,s->first)) return -1; - if((last->data->format != output.format) || (last->data->bps != output.bps) || - (last->data->nch!=output.nch) || (last->data->rate!=output.rate)){ + if((s->last->data->format != s->output.format) || + (s->last->data->bps != s->output.bps) || + (s->last->data->nch != s->output.nch) || + (s->last->data->rate != s->output.rate)) { // Something is stuffed audio out will not work mp_msg(MSGT_AFILTER,MSGL_ERR,"Unable to setup filter system can not meet sound-card demands, please report this error on MPlayer development mailing list. \n"); - af_uninit(); + af_uninit(s); return -1; } } @@ -370,9 +354,9 @@ } // Filter data chunk through the filters in the list -af_data_t* af_play(af_data_t* data) +af_data_t* af_play(af_stream_t* s, af_data_t* data) { - af_instance_t* af=first; + af_instance_t* af=s->first; // Iterate through all filters do{ data=af->play(af,data); @@ -390,9 +374,9 @@ /* Calculate how long the output from the filters will be given the input length "len" */ -int af_outputlen(int len) +int af_outputlen(af_stream_t* s, int len) { - af_instance_t* af=first; + af_instance_t* af=s->first; frac_t mul = {1,1}; // Iterate through all filters do{ @@ -406,9 +390,9 @@ /* Calculate how long the input to the filters should be to produce a certain output length, i.e. the return value of this function is the input length required to produce the output length "len". */ -int af_inputlen(int len) +int af_inputlen(af_stream_t* s, int len) { - af_instance_t* af=first; + af_instance_t* af=s->first; frac_t mul = {1,1}; // Iterate through all filters do{ diff -r a0bba1b6c458 -r 8819fdf88b5d libaf/af.h --- a/libaf/af.h Tue Oct 01 09:20:27 2002 +0000 +++ b/libaf/af.h Tue Oct 01 12:53:30 2002 +0000 @@ -47,6 +47,31 @@ the length of the buffer. */ }af_instance_t; +// Initialization types +#define SLOW 1 +#define FAST 2 +#define FORCE 3 + +// Configuration switches +typedef struct af_cfg_s{ + int force; // Initialization type + char** list; /* list of names of plugins that are added to filter + list during first initialization of stream */ +}af_cfg_t; + +// Current audio stream +typedef struct af_stream_s +{ + // The first and last filter in the list + af_instance_t* first; + af_instance_t* last; + // Storage for input and output data formats + af_data_t input; + af_data_t output; + // Cofiguration for this stream + af_cfg_t cfg; +}af_stream_t; + /********************************************* // Control parameters */ @@ -97,35 +122,28 @@ #define AF_NA -3 -/********************************************* -// Command line configuration switches -*/ -typedef struct af_cfg_s{ - int rate; - int format; - int bps; - int force; - char** list; -}af_cfg_t; - // Export functions -/* Init read configuration and create filter list accordingly. In and - out contains the format of the current movie and the formate of the - prefered output respectively */ -int af_init(af_data_t* in, af_data_t* out); +/* Initialize the stream "s". This function creates a new fileterlist + if nessesary according to the values set in input and output. Input + and output should contain the format of the current movie and the + formate of the preferred output respectively. The function is + reentreant i.e. if called wit an already initialized stream the + stream will be reinitialized. The return value is 0 if sucess and + -1 if failure */ +int af_init(af_stream_t* s); // Uninit and remove all filters -void af_uninit(); +void af_uninit(af_stream_t* s); // Filter data chunk through the filters in the list -af_data_t* af_play(af_data_t* data); +af_data_t* af_play(af_stream_t* s, af_data_t* data); /* Calculate how long the output from the filters will be given the input length "len" */ -int af_outputlen(int len); +int af_outputlen(af_stream_t* s, int len); /* Calculate how long the input to the filters should be to produce a certain output length, i.e. the return value of this function is the input length required to produce the output length "len". */ -int af_inputlen(int len); +int af_inputlen(af_stream_t* s, int len); @@ -153,8 +171,4 @@ #define max(a,b)(((a)>(b))?(a):(b)) #endif -#ifndef AUDIO_FILTER -extern af_cfg_t af_cfg; -#endif /* AUDIO_FILTER */ - #endif diff -r a0bba1b6c458 -r 8819fdf88b5d libaf/af_format.c --- a/libaf/af_format.c Tue Oct 01 09:20:27 2002 +0000 +++ b/libaf/af_format.c Tue Oct 01 12:53:30 2002 +0000 @@ -97,7 +97,7 @@ } af->data->bps=((af_data_t*)arg)->bps; - mp_msg(MSGT_AFILTER,MSGL_STATUS,"[format] Changing number sample format to 0x%08X and/or bytes per sample to %i \n",af->data->format,af->data->bps); + mp_msg(MSGT_AFILTER,MSGL_V,"[format] Changing number sample format to 0x%08X and/or bytes per sample to %i \n",af->data->format,af->data->bps); return AF_OK; } return AF_UNKNOWN; diff -r a0bba1b6c458 -r 8819fdf88b5d libaf/af_resample.c --- a/libaf/af_resample.c Tue Oct 01 09:20:27 2002 +0000 +++ b/libaf/af_resample.c Tue Oct 01 12:53:30 2002 +0000 @@ -277,7 +277,7 @@ } af->data->rate=((int*)arg)[0]; - mp_msg(MSGT_AFILTER,MSGL_STATUS,"[resample] Changing sample rate to %iHz\n",af->data->rate); + mp_msg(MSGT_AFILTER,MSGL_V,"[resample] Changing sample rate to %iHz\n",af->data->rate); return AF_OK; } return AF_UNKNOWN;