1 /*****************************************************************************
2 * filters.c : audio output filters management
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: filters.c,v 1.3 2002/08/12 09:34:15 sam Exp $
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* calloc(), malloc(), free() */
36 #include "audio_output.h"
37 #include "aout_internal.h"
39 /*****************************************************************************
40 * aout_FiltersCreatePipeline: create a filters pipeline to transform a sample
42 *****************************************************************************
43 * TODO : allow the user to add/remove specific filters
44 *****************************************************************************/
45 int aout_FiltersCreatePipeline( aout_instance_t * p_aout,
46 aout_filter_t ** pp_filters,
48 audio_sample_format_t * p_input_format,
49 audio_sample_format_t * p_output_format )
51 if ( AOUT_FMTS_IDENTICAL( p_input_format, p_output_format ) )
53 msg_Dbg( p_aout, "no need for any filter" );
58 pp_filters[0] = vlc_object_create( p_aout, sizeof(aout_filter_t) );
59 if ( pp_filters[0] == NULL )
63 vlc_object_attach( pp_filters[0], p_aout );
65 /* Try to find a filter to do the whole conversion. */
66 memcpy( &pp_filters[0]->input, p_input_format,
67 sizeof(audio_sample_format_t) );
68 memcpy( &pp_filters[0]->output, p_output_format,
69 sizeof(audio_sample_format_t) );
70 pp_filters[0]->p_module = module_Need( pp_filters[0], "audio filter",
72 if ( pp_filters[0]->p_module != NULL )
74 msg_Dbg( p_aout, "found a filter for the whole conversion" );
79 /* Split the conversion : format | rate, or rate | format. */
80 pp_filters[0]->output.i_format = pp_filters[0]->input.i_format;
81 pp_filters[0]->p_module = module_Need( pp_filters[0], "audio filter",
83 if ( pp_filters[0]->p_module == NULL )
85 /* Then, start with the format conversion. */
86 memcpy( &pp_filters[0]->output, p_output_format,
87 sizeof(audio_sample_format_t) );
88 pp_filters[0]->output.i_rate = pp_filters[0]->input.i_rate;
89 pp_filters[0]->p_module = module_Need( pp_filters[0], "audio filter",
91 if ( pp_filters[0]->p_module == NULL )
93 msg_Err( p_aout, "couldn't find a filter for any conversion" );
94 vlc_object_detach( pp_filters[0] );
95 vlc_object_destroy( pp_filters[0] );
100 /* Find a filter for the rest. */
101 pp_filters[1] = vlc_object_create( p_aout, sizeof(aout_filter_t) );
102 if ( pp_filters[1] == NULL )
104 vlc_object_detach( pp_filters[0] );
105 vlc_object_destroy( pp_filters[0] );
108 vlc_object_attach( pp_filters[1], p_aout );
110 memcpy( &pp_filters[1]->input, &pp_filters[0]->output,
111 sizeof(audio_sample_format_t) );
112 memcpy( &pp_filters[1]->output, p_output_format,
113 sizeof(audio_sample_format_t) );
114 pp_filters[1]->p_module = module_Need( pp_filters[1], "audio filter",
116 if ( pp_filters[1]->p_module == NULL )
119 "couldn't find a filter for the 2nd part of the conversion" );
120 vlc_object_detach( pp_filters[0] );
121 vlc_object_destroy( pp_filters[0] );
122 vlc_object_detach( pp_filters[1] );
123 vlc_object_destroy( pp_filters[1] );
127 msg_Dbg( p_aout, "filter pipeline made of two filters" );
133 /*****************************************************************************
134 * aout_FiltersDestroyPipeline: deallocate a filters pipeline
135 *****************************************************************************/
136 void aout_FiltersDestroyPipeline( aout_instance_t * p_aout,
137 aout_filter_t ** pp_filters,
142 for ( i = 0; i < i_nb_filters; i++ )
144 module_Unneed( pp_filters[i], pp_filters[i]->p_module );
145 vlc_object_detach( pp_filters[i] );
146 vlc_object_destroy( pp_filters[i] );
150 /*****************************************************************************
151 * aout_FiltersHintBuffers: fill in aout_alloc_t structures to optimize
153 *****************************************************************************/
154 void aout_FiltersHintBuffers( aout_instance_t * p_aout,
155 aout_filter_t ** pp_filters,
156 int i_nb_filters, aout_alloc_t * p_first_alloc )
160 for ( i = i_nb_filters - 1; i >= 0; i-- )
162 aout_filter_t * p_filter = pp_filters[i];
164 int i_output_size = aout_FormatToByterate( &p_filter->output,
165 p_filter->output.i_rate );
166 int i_input_size = aout_FormatToByterate( &p_filter->input,
167 p_filter->input.i_rate );
169 p_first_alloc->i_bytes_per_sec = __MAX( p_first_alloc->i_bytes_per_sec,
172 if ( p_filter->b_in_place )
174 p_first_alloc->i_bytes_per_sec = __MAX(
175 p_first_alloc->i_bytes_per_sec,
180 /* We're gonna need a buffer allocation. */
181 memcpy( &p_filter->output_alloc, p_first_alloc,
182 sizeof(aout_alloc_t) );
183 p_first_alloc->i_alloc_type = AOUT_ALLOC_STACK;
184 p_first_alloc->i_bytes_per_sec = i_input_size;
189 /*****************************************************************************
190 * aout_FiltersPlay: play a buffer
191 *****************************************************************************/
192 void aout_FiltersPlay( aout_instance_t * p_aout,
193 aout_filter_t ** pp_filters,
194 int i_nb_filters, aout_buffer_t ** pp_input_buffer )
198 for ( i = 0; i < i_nb_filters; i++ )
200 aout_filter_t * p_filter = pp_filters[i];
201 aout_buffer_t * p_output_buffer;
203 aout_BufferAlloc( &p_filter->output_alloc,
204 (u64)((*pp_input_buffer)->i_nb_samples * 1000000)
205 / p_filter->output.i_rate, *pp_input_buffer,
207 if ( p_output_buffer == NULL )
209 msg_Err( p_aout, "out of memory" );
212 /* Please note that p_output_buffer->i_nb_samples shall be set by
213 * the filter plug-in. */
215 p_filter->pf_do_work( p_aout, p_filter, *pp_input_buffer,
218 if ( !p_filter->b_in_place )
220 aout_BufferFree( *pp_input_buffer );
221 *pp_input_buffer = p_output_buffer;