From 3ef4629545772e39aeed57195521e78fe5c08aaa Mon Sep 17 00:00:00 2001 From: anders Date: Tue, 1 Oct 2002 12:53:30 +0000 Subject: Adding support for multiple audio streams and removing annoying message from resample and format git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@7572 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libaf/af.c | 182 ++++++++++++++++++++++++++++--------------------------------- 1 file changed, 83 insertions(+), 99 deletions(-) (limited to 'libaf/af.c') diff --git a/libaf/af.c b/libaf/af.c index 39b34d8ab5..85569efba6 100644 --- a/libaf/af.c +++ b/libaf/af.c @@ -27,28 +27,6 @@ static af_info_t* filter_list[]={ \ 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 @@ af_instance_t* af_create(char* name) /* 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_instance_t* af_prepend(af_instance_t* af, char* name) 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_instance_t* af_append(af_instance_t* af, char* name) 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 @@ void af_remove(af_instance_t* af) 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 @@ void af_remove(af_instance_t* af) } /* 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 @@ int af_reinit(af_instance_t* af) // 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 @@ int af_reinit(af_instance_t* af) 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 @@ int af_reinit(af_instance_t* af) } 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 @@ int af_reinit(af_instance_t* af) /* 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 @@ af_instance_t* af_get(char* name) } // 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 @@ int af_init(af_data_t* in, af_data_t* out) 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 @@ int af_init(af_data_t* in, af_data_t* out) } // 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 @@ inline int af_lencalc(frac_t mul, int len){ /* 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 @@ int af_outputlen(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) { - af_instance_t* af=first; + af_instance_t* af=s->first; frac_t mul = {1,1}; // Iterate through all filters do{ -- cgit v1.2.3