1 /*****************************************************************************
2 * filters.c : audio output filters management
3 *****************************************************************************
4 * Copyright (C) 2002-2007 the VideoLAN team
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_dialog.h>
35 #include <vlc_modules.h>
38 #include <vlc_filter.h>
39 #include "aout_internal.h"
42 block_t
*aout_FilterBufferNew( filter_t
*p_filter
, int size
)
45 return block_Alloc( size
);
48 /*****************************************************************************
49 * FindFilter: find an audio filter for a specific transformation
50 *****************************************************************************/
51 static filter_t
* FindFilter( aout_instance_t
* p_aout
,
52 const audio_sample_format_t
* p_input_format
,
53 const audio_sample_format_t
* p_output_format
)
55 static const char typename
[] = "audio filter";
58 p_filter
= vlc_custom_create( p_aout
, sizeof(*p_filter
),
59 VLC_OBJECT_GENERIC
, typename
);
61 if ( p_filter
== NULL
) return NULL
;
62 vlc_object_attach( p_filter
, p_aout
);
64 memcpy( &p_filter
->fmt_in
.audio
, p_input_format
,
65 sizeof(audio_sample_format_t
) );
66 p_filter
->fmt_in
.i_codec
= p_input_format
->i_format
;
67 memcpy( &p_filter
->fmt_out
.audio
, p_output_format
,
68 sizeof(audio_sample_format_t
) );
69 p_filter
->fmt_out
.i_codec
= p_output_format
->i_format
;
70 p_filter
->pf_audio_buffer_new
= aout_FilterBufferNew
;
72 p_filter
->p_module
= module_need( p_filter
, "audio filter", NULL
, false );
73 if ( p_filter
->p_module
== NULL
)
75 vlc_object_release( p_filter
);
79 assert( p_filter
->pf_audio_filter
);
83 /*****************************************************************************
84 * SplitConversion: split a conversion in two parts
85 *****************************************************************************
86 * Returns the number of conversions required by the first part - 0 if only
87 * one conversion was asked.
88 * Beware : p_output_format can be modified during this function if the
89 * developer passed SplitConversion( toto, titi, titi, ... ). That is legal.
90 * SplitConversion( toto, titi, toto, ... ) isn't.
91 *****************************************************************************/
92 static int SplitConversion( const audio_sample_format_t
* p_input_format
,
93 const audio_sample_format_t
* p_output_format
,
94 audio_sample_format_t
* p_middle_format
)
97 (p_input_format
->i_format
!= p_output_format
->i_format
);
98 bool b_rate
= (p_input_format
->i_rate
!= p_output_format
->i_rate
);
100 (p_input_format
->i_physical_channels
101 != p_output_format
->i_physical_channels
)
102 || (p_input_format
->i_original_channels
103 != p_output_format
->i_original_channels
);
104 int i_nb_conversions
= b_format
+ b_rate
+ b_channels
;
106 if ( i_nb_conversions
<= 1 ) return 0;
108 memcpy( p_middle_format
, p_output_format
, sizeof(audio_sample_format_t
) );
110 if ( i_nb_conversions
== 2 )
112 if ( !b_format
|| !b_channels
)
114 p_middle_format
->i_rate
= p_input_format
->i_rate
;
115 aout_FormatPrepare( p_middle_format
);
120 p_middle_format
->i_physical_channels
121 = p_input_format
->i_physical_channels
;
122 p_middle_format
->i_original_channels
123 = p_input_format
->i_original_channels
;
124 aout_FormatPrepare( p_middle_format
);
128 /* i_nb_conversion == 3 */
129 p_middle_format
->i_rate
= p_input_format
->i_rate
;
130 aout_FormatPrepare( p_middle_format
);
134 static void ReleaseFilter( filter_t
* p_filter
)
136 module_unneed( p_filter
, p_filter
->p_module
);
137 vlc_object_release( p_filter
);
140 /*****************************************************************************
141 * aout_FiltersCreatePipeline: create a filters pipeline to transform a sample
143 *****************************************************************************
144 * pi_nb_filters must be initialized before calling this function
145 *****************************************************************************/
146 int aout_FiltersCreatePipeline( aout_instance_t
* p_aout
,
147 filter_t
** pp_filters_start
,
149 const audio_sample_format_t
* p_input_format
,
150 const audio_sample_format_t
* p_output_format
)
152 filter_t
** pp_filters
= pp_filters_start
+ *pi_nb_filters
;
153 audio_sample_format_t temp_format
;
154 int i_nb_conversions
;
156 if ( AOUT_FMTS_IDENTICAL( p_input_format
, p_output_format
) )
158 msg_Dbg( p_aout
, "no need for any filter" );
162 aout_FormatsPrint( p_aout
, "filter(s)", p_input_format
, p_output_format
);
164 if( *pi_nb_filters
+ 1 > AOUT_MAX_FILTERS
)
166 msg_Err( p_aout
, "max filter reached (%d)", AOUT_MAX_FILTERS
);
167 dialog_Fatal( p_aout
, _("Audio filtering failed"),
168 _("The maximum number of filters (%d) was reached."),
173 /* Try to find a filter to do the whole conversion. */
174 pp_filters
[0] = FindFilter( p_aout
, p_input_format
, p_output_format
);
175 if ( pp_filters
[0] != NULL
)
177 msg_Dbg( p_aout
, "found a filter for the whole conversion" );
182 /* We'll have to split the conversion. We always do the downmixing
183 * before the resampling, because the audio decoder can probably do it
185 i_nb_conversions
= SplitConversion( p_input_format
,
186 p_output_format
, &temp_format
);
187 if ( !i_nb_conversions
)
189 /* There was only one conversion to do, and we already failed. */
190 msg_Err( p_aout
, "couldn't find a filter for the conversion "
192 &p_input_format
->i_format
, &p_output_format
->i_format
);
196 pp_filters
[0] = FindFilter( p_aout
, p_input_format
, &temp_format
);
197 if ( pp_filters
[0] == NULL
&& i_nb_conversions
== 2 )
199 /* Try with only one conversion. */
200 SplitConversion( p_input_format
, &temp_format
, &temp_format
);
201 pp_filters
[0] = FindFilter( p_aout
, p_input_format
, &temp_format
);
203 if ( pp_filters
[0] == NULL
)
206 "couldn't find a filter for the first part of the conversion" );
210 /* We have the first stage of the conversion. Find a filter for
212 if( *pi_nb_filters
+ 2 > AOUT_MAX_FILTERS
)
214 ReleaseFilter( pp_filters
[0] );
215 msg_Err( p_aout
, "max filter reached (%d)", AOUT_MAX_FILTERS
);
216 dialog_Fatal( p_aout
, _("Audio filtering failed"),
217 _("The maximum number of filters (%d) was reached."),
221 pp_filters
[1] = FindFilter( p_aout
, &pp_filters
[0]->fmt_out
.audio
,
223 if ( pp_filters
[1] == NULL
)
225 /* Try to split the conversion. */
226 i_nb_conversions
= SplitConversion( &pp_filters
[0]->fmt_out
.audio
,
227 p_output_format
, &temp_format
);
228 if ( !i_nb_conversions
)
230 ReleaseFilter( pp_filters
[0] );
232 "couldn't find a filter for the second part of the conversion" );
235 if( *pi_nb_filters
+ 3 > AOUT_MAX_FILTERS
)
237 ReleaseFilter( pp_filters
[0] );
238 msg_Err( p_aout
, "max filter reached (%d)", AOUT_MAX_FILTERS
);
239 dialog_Fatal( p_aout
, _("Audio filtering failed"),
240 _("The maximum number of filters (%d) was reached."),
244 pp_filters
[1] = FindFilter( p_aout
, &pp_filters
[0]->fmt_out
.audio
,
246 pp_filters
[2] = FindFilter( p_aout
, &temp_format
,
249 if ( pp_filters
[1] == NULL
|| pp_filters
[2] == NULL
)
251 ReleaseFilter( pp_filters
[0] );
252 if ( pp_filters
[1] != NULL
)
254 ReleaseFilter( pp_filters
[1] );
256 if ( pp_filters
[2] != NULL
)
258 ReleaseFilter( pp_filters
[2] );
261 "couldn't find filters for the second part of the conversion" );
265 msg_Dbg( p_aout
, "found 3 filters for the whole conversion" );
270 msg_Dbg( p_aout
, "found 2 filters for the whole conversion" );
276 /*****************************************************************************
277 * aout_FiltersDestroyPipeline: deallocate a filters pipeline
278 *****************************************************************************/
279 void aout_FiltersDestroyPipeline( aout_instance_t
* p_aout
,
280 filter_t
** pp_filters
,
286 for ( i
= 0; i
< i_nb_filters
; i
++ )
288 filter_t
*p_filter
= pp_filters
[i
];
290 module_unneed( p_filter
, p_filter
->p_module
);
291 free( p_filter
->p_owner
);
292 vlc_object_release( p_filter
);
296 /*****************************************************************************
297 * aout_FiltersHintBuffers: fill in aout_alloc_t structures to optimize
299 *****************************************************************************/
300 void aout_FiltersHintBuffers( aout_instance_t
* p_aout
,
301 filter_t
** pp_filters
,
302 int i_nb_filters
, aout_alloc_t
* p_first_alloc
)
306 (void)p_aout
; /* unused */
308 for ( i
= i_nb_filters
- 1; i
>= 0; i
-- )
310 filter_t
* p_filter
= pp_filters
[i
];
312 int i_output_size
= p_filter
->fmt_out
.audio
.i_bytes_per_frame
313 * p_filter
->fmt_out
.audio
.i_rate
* AOUT_MAX_INPUT_RATE
314 / p_filter
->fmt_out
.audio
.i_frame_length
;
315 int i_input_size
= p_filter
->fmt_in
.audio
.i_bytes_per_frame
316 * p_filter
->fmt_in
.audio
.i_rate
* AOUT_MAX_INPUT_RATE
317 / p_filter
->fmt_in
.audio
.i_frame_length
;
319 if( i_output_size
> p_first_alloc
->i_bytes_per_sec
)
320 p_first_alloc
->i_bytes_per_sec
= i_output_size
;
321 if( i_input_size
> p_first_alloc
->i_bytes_per_sec
)
322 p_first_alloc
->i_bytes_per_sec
= i_input_size
;
326 /*****************************************************************************
327 * aout_FiltersPlay: play a buffer
328 *****************************************************************************/
329 void aout_FiltersPlay( filter_t
** pp_filters
,
330 unsigned i_nb_filters
, block_t
** pp_block
)
332 block_t
*p_block
= *pp_block
;
334 /* TODO: use filter chain */
335 for( unsigned i
= 0; i
< i_nb_filters
; i
++ )
337 filter_t
* p_filter
= pp_filters
[i
];
339 /* Please note that p_block->i_nb_samples & i_buffer
340 * shall be set by the filter plug-in. */
341 p_block
= p_filter
->pf_audio_filter( p_filter
, p_block
);