comparison libaf/af.c @ 7568:d08513b9fed6

Adding new audio output filter layer libaf
author anders
date Tue, 01 Oct 2002 06:45:08 +0000
parents
children 8819fdf88b5d
comparison
equal deleted inserted replaced
7567:85e9956a6727 7568:d08513b9fed6
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #ifdef HAVE_MALLOC_H
6 #include <malloc.h>
7 #endif
8
9 #include "../config.h"
10 #include "../mp_msg.h"
11
12 #include "af.h"
13
14 // Static list of filters
15 extern af_info_t af_info_dummy;
16 extern af_info_t af_info_delay;
17 extern af_info_t af_info_channels;
18 extern af_info_t af_info_format;
19 extern af_info_t af_info_resample;
20
21 static af_info_t* filter_list[]={ \
22 &af_info_dummy,\
23 &af_info_delay,\
24 &af_info_channels,\
25 &af_info_format,\
26 &af_info_resample,\
27 NULL \
28 };
29
30 // Command line config switches
31 af_cfg_t af_cfg={\
32 0,\
33 0,\
34 0,\
35 0,\
36 NULL,\
37 };
38
39
40 // Initialization types
41 #define SLOW 1
42 #define FAST 2
43 #define FORCE 3
44
45 // The first and last filter in the list
46 static af_instance_t* first=NULL;
47 static af_instance_t* last=NULL;
48 // Storage for input and output data formats (set by init)
49 static af_data_t input;
50 static af_data_t output;
51
52 /* Find a filter in the static list of filters using it's name. This
53 function is used internally */
54 af_info_t* af_find(char*name)
55 {
56 int i=0;
57 while(filter_list[i]){
58 if(!strcmp(filter_list[i]->name,name))
59 return filter_list[i];
60 i++;
61 }
62 mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't find audio filter '%s'\n",name);
63 return NULL;
64 }
65
66 // Function for creating a new filter of type name
67 af_instance_t* af_create(char* name)
68 {
69 // Allocate space for the new filter and reset all pointers
70 af_instance_t* new=malloc(sizeof(af_instance_t));
71 if(!new){
72 mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory\n");
73 return NULL;
74 }
75 memset(new,0,sizeof(af_instance_t));
76
77 // Find filter from name
78 new->info=af_find(name);
79
80 // Initialize the new filter
81 if(new->info && (AF_OK==new->info->open(new)))
82 return new;
83
84 free(new);
85 mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't create audio filter '%s'\n",name);
86 return NULL;
87 }
88
89 /* Create and insert a new filter of type name before the filter in the
90 argument. This function can be called during runtime, the return
91 value is the new filter */
92 af_instance_t* af_prepend(af_instance_t* af, char* name)
93 {
94 // Create the new filter and make sure it is ok
95 af_instance_t* new=af_create(name);
96 if(!new)
97 return NULL;
98 // Update pointers
99 new->next=af;
100 if(af){
101 new->prev=af->prev;
102 af->prev=new;
103 }
104 else
105 last=new;
106 if(new->prev)
107 new->prev->next=new;
108 else
109 first=new;
110 return new;
111 }
112
113 /* Create and insert a new filter of type name after the filter in the
114 argument. This function can be called during runtime, the return
115 value is the new filter */
116 af_instance_t* af_append(af_instance_t* af, char* name)
117 {
118 // Create the new filter and make sure it is OK
119 af_instance_t* new=af_create(name);
120 if(!new)
121 return NULL;
122 // Update pointers
123 new->prev=af;
124 if(af){
125 new->next=af->next;
126 af->next=new;
127 }
128 else
129 first=new;
130 if(new->next)
131 new->next->prev=new;
132 else
133 last=new;
134 return new;
135 }
136
137 // Uninit and remove the filter "af"
138 void af_remove(af_instance_t* af)
139 {
140 if(!af) return;
141
142 // Detach pointers
143 if(af->prev)
144 af->prev->next=af->next;
145 else
146 first=af->next;
147 if(af->next)
148 af->next->prev=af->prev;
149 else
150 last=af->prev;
151
152 // Uninitialize af and free memory
153 af->uninit(af);
154 free(af);
155 }
156
157 /* Reinitializes all filters downstream from the filter given in the argument */
158 int af_reinit(af_instance_t* af)
159 {
160 if(!af)
161 return AF_ERROR;
162
163 do{
164 af_data_t in; // Format of the input to current filter
165 int rv=0; // Return value
166
167 // Check if this is the first filter
168 if(!af->prev)
169 memcpy(&in,&input,sizeof(af_data_t));
170 else
171 memcpy(&in,af->prev->data,sizeof(af_data_t));
172 // Reset just in case...
173 in.audio=NULL;
174 in.len=0;
175
176 rv = af->control(af,AF_CONTROL_REINIT,&in);
177 switch(rv){
178 case AF_OK:
179 break;
180 case AF_FALSE:{ // Configuration filter is needed
181 af_instance_t* new = NULL;
182 // Insert channels filter
183 if((af->prev?af->prev->data->nch:input.nch) != in.nch){
184 // Create channels filter
185 if(NULL == (new = af_prepend(af,"channels")))
186 return AF_ERROR;
187 // Set number of output channels
188 if(AF_OK != (rv = new->control(new,AF_CONTROL_CHANNELS,&in.nch)))
189 return rv;
190 // Initialize channels filter
191 if(!new->prev)
192 memcpy(&in,&input,sizeof(af_data_t));
193 else
194 memcpy(&in,new->prev->data,sizeof(af_data_t));
195 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
196 return rv;
197 }
198 // Insert format filter
199 if(((af->prev?af->prev->data->format:input.format) != in.format) ||
200 ((af->prev?af->prev->data->bps:input.bps) != in.bps)){
201 // Create format filter
202 if(NULL == (new = af_prepend(af,"format")))
203 return AF_ERROR;
204 // Set output format
205 if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in)))
206 return rv;
207 // Initialize format filter
208 if(!new->prev)
209 memcpy(&in,&input,sizeof(af_data_t));
210 else
211 memcpy(&in,new->prev->data,sizeof(af_data_t));
212 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
213 return rv;
214 }
215 if(!new) // Should _never_ happen
216 return AF_ERROR;
217 af=new;
218 break;
219 }
220 case AF_DETACH:{ // Filter is redundant and wants to be unloaded
221 af_instance_t* aft=af->prev;
222 af_remove(af);
223 if(aft)
224 af=aft;
225 else
226 af=first; // Restart configuration
227 break;
228 }
229 default:
230 mp_msg(MSGT_AFILTER,MSGL_ERR,"Reinit did not work, audio filter '%s' returned error code %i\n",af->info->name,rv);
231 return AF_ERROR;
232 }
233 af=af->next;
234 }while(af);
235 return AF_OK;
236 }
237
238 /* Find filter in the dynamic filter list using it's name This
239 function is used for finding already initialized filters */
240 af_instance_t* af_get(char* name)
241 {
242 af_instance_t* af=first;
243 while(af->next != NULL){
244 if(!strcmp(af->info->name,name))
245 return af;
246 af=af->next;
247 }
248 return NULL;
249 }
250
251 // Uninit and remove all filters
252 void af_uninit()
253 {
254 while(first)
255 af_remove(first);
256 }
257
258 /* Init read configuration and create filter list accordingly. In and
259 out contains the format of the current movie and the formate of the
260 preferred output respectively */
261 int af_init(af_data_t* in, af_data_t* out)
262 {
263 int cfg=SLOW; // configuration type
264 int i=0;
265
266 // Precaution in case caller is misbehaving
267 in->audio = out->audio = NULL;
268 in->len = out->len = 0;
269
270 // Figure out how fast the machine is
271 if(af_cfg.force)
272 cfg=af_cfg.force;
273 else{
274 # if defined(HAVE_SSE) || defined(HAVE_3DNOWEX)
275 cfg=FAST;
276 # else
277 cfg=SLOW;
278 # endif
279 }
280
281 // Input and output configuration
282 memcpy(&input,in,sizeof(af_data_t));
283 memcpy(&output,out,sizeof(af_data_t));
284
285 // Check if this is the first call
286 if(!first){
287 // Add all filters in the list (if there are any)
288 if(!af_cfg.list){
289 if(!af_append(first,"dummy")) // To make automatic format conversion work
290 return -1;
291 }
292 else{
293 while(af_cfg.list[i]){
294 if(!af_append(last,af_cfg.list[i++]))
295 return -1;
296 }
297 }
298 }
299
300 // Init filters
301 if(AF_OK != af_reinit(first))
302 return -1;
303
304 // Check output format
305 if(cfg!=FORCE){
306 af_instance_t* af = NULL; // New filter
307 // Check output frequency if not OK fix with resample
308 if(last->data->rate!=output.rate){
309 if(NULL==(af=af_get("resample"))){
310 if(cfg==SLOW){
311 if(!strcmp(first->info->name,"format"))
312 af = af_append(first,"resample");
313 else
314 af = af_prepend(first,"resample");
315 }
316 else{
317 if(!strcmp(last->info->name,"format"))
318 af = af_prepend(last,"resample");
319 else
320 af = af_append(last,"resample");
321 }
322 }
323 // Init the new filter
324 if(!af || (AF_OK != af->control(af,AF_CONTROL_RESAMPLE,&output.rate)))
325 return -1;
326 if(AF_OK != af_reinit(af))
327 return -1;
328 }
329
330 // Check number of output channels fix if not OK
331 // If needed always inserted last -> easy to screw up other filters
332 if(last->data->nch!=output.nch){
333 if(!strcmp(last->info->name,"format"))
334 af = af_prepend(last,"channels");
335 else
336 af = af_append(last,"channels");
337 // Init the new filter
338 if(!af || (AF_OK != af->control(af,AF_CONTROL_CHANNELS,&output.nch)))
339 return -1;
340 if(AF_OK != af_reinit(af))
341 return -1;
342 }
343
344 // Check output format fix if not OK
345 if((last->data->format != output.format) || (last->data->bps != output.bps)){
346 if(strcmp(last->info->name,"format"))
347 af = af_append(last,"format");
348 else
349 af = last;
350 // Init the new filter
351 if(!af ||(AF_OK != af->control(af,AF_CONTROL_FORMAT,&output)))
352 return -1;
353 if(AF_OK != af_reinit(af))
354 return -1;
355 }
356
357 // Re init again just in case
358 if(AF_OK != af_reinit(first))
359 return -1;
360
361 if((last->data->format != output.format) || (last->data->bps != output.bps) ||
362 (last->data->nch!=output.nch) || (last->data->rate!=output.rate)){
363 // Something is stuffed audio out will not work
364 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");
365 af_uninit();
366 return -1;
367 }
368 }
369 return 0;
370 }
371
372 // Filter data chunk through the filters in the list
373 af_data_t* af_play(af_data_t* data)
374 {
375 af_instance_t* af=first;
376 // Iterate through all filters
377 do{
378 data=af->play(af,data);
379 af=af->next;
380 }while(af);
381 return data;
382 }
383
384 /* Helper function used to calculate the exact buffer length needed
385 when buffers are resized */
386 inline int af_lencalc(frac_t mul, int len){
387 register int q = len*mul.n;
388 return q/mul.d + q%mul.d;
389 }
390
391 /* Calculate how long the output from the filters will be given the
392 input length "len" */
393 int af_outputlen(int len)
394 {
395 af_instance_t* af=first;
396 frac_t mul = {1,1};
397 // Iterate through all filters
398 do{
399 mul.n *= af->mul.n;
400 mul.d *= af->mul.d;
401 af=af->next;
402 }while(af);
403 return af_lencalc(mul,len);
404 }
405
406 /* Calculate how long the input to the filters should be to produce a
407 certain output length, i.e. the return value of this function is
408 the input length required to produce the output length "len". */
409 int af_inputlen(int len)
410 {
411 af_instance_t* af=first;
412 frac_t mul = {1,1};
413 // Iterate through all filters
414 do{
415 mul.d *= af->mul.n;
416 mul.n *= af->mul.d;
417 af=af->next;
418 }while(af);
419 return af_lencalc(mul,len);
420 }
421
422 /* Helper function called by the macro with the same name this
423 function should not be called directly */
424 inline int af_resize_local_buffer(af_instance_t* af, af_data_t* data)
425 {
426 // Calculate new length
427 register int len = af_lencalc(af->mul,data->len);
428 mp_msg(MSGT_AFILTER,MSGL_V,"Reallocating memory in module %s, old len = %i, new len = %i\n",af->info->name,af->data->len,len);
429 // If there is a buffer free it
430 if(af->data->audio)
431 free(af->data->audio);
432 // Create new buffer and check that it is OK
433 af->data->audio = malloc(len);
434 if(!af->data->audio){
435 mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory \n");
436 return AF_ERROR;
437 }
438 af->data->len=len;
439 return AF_OK;
440 }