00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include <vlc/vlc.h>
00031
00032 #ifdef HAVE_ALLOCA_H
00033 # include <alloca.h>
00034 #endif
00035
00036 #include "audio_output.h"
00037 #include "aout_internal.h"
00038
00039
00040
00041
00042 static aout_filter_t * FindFilter( aout_instance_t * p_aout,
00043 const audio_sample_format_t * p_input_format,
00044 const audio_sample_format_t * p_output_format )
00045 {
00046 aout_filter_t * p_filter = vlc_object_create( p_aout,
00047 sizeof(aout_filter_t) );
00048
00049 if ( p_filter == NULL ) return NULL;
00050 vlc_object_attach( p_filter, p_aout );
00051
00052 memcpy( &p_filter->input, p_input_format, sizeof(audio_sample_format_t) );
00053 memcpy( &p_filter->output, p_output_format,
00054 sizeof(audio_sample_format_t) );
00055 p_filter->p_module = module_Need( p_filter, "audio filter", NULL, 0 );
00056 if ( p_filter->p_module == NULL )
00057 {
00058 vlc_object_detach( p_filter );
00059 vlc_object_destroy( p_filter );
00060 return NULL;
00061 }
00062
00063 p_filter->b_continuity = VLC_FALSE;
00064
00065 return p_filter;
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 static int SplitConversion( const audio_sample_format_t * p_input_format,
00078 const audio_sample_format_t * p_output_format,
00079 audio_sample_format_t * p_middle_format )
00080 {
00081 vlc_bool_t b_format =
00082 (p_input_format->i_format != p_output_format->i_format);
00083 vlc_bool_t b_rate = (p_input_format->i_rate != p_output_format->i_rate);
00084 vlc_bool_t b_channels =
00085 (p_input_format->i_physical_channels
00086 != p_output_format->i_physical_channels)
00087 || (p_input_format->i_original_channels
00088 != p_output_format->i_original_channels);
00089 int i_nb_conversions = b_format + b_rate + b_channels;
00090
00091 if ( i_nb_conversions <= 1 ) return 0;
00092
00093 memcpy( p_middle_format, p_output_format, sizeof(audio_sample_format_t) );
00094
00095 if ( i_nb_conversions == 2 )
00096 {
00097 if ( !b_format || !b_channels )
00098 {
00099 p_middle_format->i_rate = p_input_format->i_rate;
00100 aout_FormatPrepare( p_middle_format );
00101 return 1;
00102 }
00103
00104
00105 p_middle_format->i_physical_channels
00106 = p_input_format->i_physical_channels;
00107 p_middle_format->i_original_channels
00108 = p_input_format->i_original_channels;
00109 aout_FormatPrepare( p_middle_format );
00110 return 1;
00111 }
00112
00113
00114 p_middle_format->i_rate = p_input_format->i_rate;
00115 aout_FormatPrepare( p_middle_format );
00116 return 2;
00117 }
00118
00119 static void ReleaseFilter( aout_filter_t * p_filter )
00120 {
00121 module_Unneed( p_filter, p_filter->p_module );
00122 vlc_object_detach( p_filter );
00123 vlc_object_destroy( p_filter );
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 int aout_FiltersCreatePipeline( aout_instance_t * p_aout,
00133 aout_filter_t ** pp_filters_start,
00134 int * pi_nb_filters,
00135 const audio_sample_format_t * p_input_format,
00136 const audio_sample_format_t * p_output_format )
00137 {
00138 aout_filter_t** pp_filters = pp_filters_start + *pi_nb_filters;
00139 audio_sample_format_t temp_format;
00140 int i_nb_conversions;
00141
00142 if ( AOUT_FMTS_IDENTICAL( p_input_format, p_output_format ) )
00143 {
00144 msg_Dbg( p_aout, "no need for any filter" );
00145 return 0;
00146 }
00147
00148 aout_FormatsPrint( p_aout, "filter(s)", p_input_format, p_output_format );
00149
00150 if( *pi_nb_filters + 1 > AOUT_MAX_FILTERS )
00151 {
00152 msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS );
00153 return -1;
00154 }
00155
00156
00157 pp_filters[0] = FindFilter( p_aout, p_input_format, p_output_format );
00158 if ( pp_filters[0] != NULL )
00159 {
00160 msg_Dbg( p_aout, "found a filter for the whole conversion" );
00161 ++*pi_nb_filters;
00162 return 0;
00163 }
00164
00165
00166
00167
00168 i_nb_conversions = SplitConversion( p_input_format,
00169 p_output_format, &temp_format );
00170 if ( !i_nb_conversions )
00171 {
00172
00173 msg_Err( p_aout, "couldn't find a filter for the conversion" );
00174 return -1;
00175 }
00176
00177 pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format );
00178 if ( pp_filters[0] == NULL && i_nb_conversions == 2 )
00179 {
00180
00181 SplitConversion( p_input_format, &temp_format, &temp_format );
00182 pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format );
00183 }
00184 if ( pp_filters[0] == NULL )
00185 {
00186 msg_Err( p_aout,
00187 "couldn't find a filter for the first part of the conversion" );
00188 return -1;
00189 }
00190
00191
00192
00193 if( *pi_nb_filters + 2 > AOUT_MAX_FILTERS )
00194 {
00195 ReleaseFilter( pp_filters[0] );
00196 msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS );
00197 return -1;
00198 }
00199 pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output,
00200 p_output_format );
00201 if ( pp_filters[1] == NULL )
00202 {
00203
00204 i_nb_conversions = SplitConversion( &pp_filters[0]->output,
00205 p_output_format, &temp_format );
00206 if ( !i_nb_conversions )
00207 {
00208 ReleaseFilter( pp_filters[0] );
00209 msg_Err( p_aout,
00210 "couldn't find a filter for the second part of the conversion" );
00211 return -1;
00212 }
00213 if( *pi_nb_filters + 3 > AOUT_MAX_FILTERS )
00214 {
00215 ReleaseFilter( pp_filters[0] );
00216 msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS );
00217 return -1;
00218 }
00219 pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output,
00220 &temp_format );
00221 pp_filters[2] = FindFilter( p_aout, &temp_format,
00222 p_output_format );
00223
00224 if ( pp_filters[1] == NULL || pp_filters[2] == NULL )
00225 {
00226 ReleaseFilter( pp_filters[0] );
00227 if ( pp_filters[1] != NULL )
00228 {
00229 ReleaseFilter( pp_filters[1] );
00230 }
00231 if ( pp_filters[2] != NULL )
00232 {
00233 ReleaseFilter( pp_filters[2] );
00234 }
00235 msg_Err( p_aout,
00236 "couldn't find filters for the second part of the conversion" );
00237 return -1;
00238 }
00239 *pi_nb_filters += 3;
00240 msg_Dbg( p_aout, "found 3 filters for the whole conversion" );
00241 }
00242 else
00243 {
00244 *pi_nb_filters += 2;
00245 msg_Dbg( p_aout, "found 2 filters for the whole conversion" );
00246 }
00247
00248 return 0;
00249 }
00250
00251
00252
00253
00254 void aout_FiltersDestroyPipeline( aout_instance_t * p_aout,
00255 aout_filter_t ** pp_filters,
00256 int i_nb_filters )
00257 {
00258 int i;
00259
00260 for ( i = 0; i < i_nb_filters; i++ )
00261 {
00262 module_Unneed( pp_filters[i], pp_filters[i]->p_module );
00263 vlc_object_detach( pp_filters[i] );
00264 vlc_object_destroy( pp_filters[i] );
00265 }
00266 }
00267
00268
00269
00270
00271
00272 void aout_FiltersHintBuffers( aout_instance_t * p_aout,
00273 aout_filter_t ** pp_filters,
00274 int i_nb_filters, aout_alloc_t * p_first_alloc )
00275 {
00276 int i;
00277
00278 (void)p_aout;
00279
00280 for ( i = i_nb_filters - 1; i >= 0; i-- )
00281 {
00282 aout_filter_t * p_filter = pp_filters[i];
00283
00284 int i_output_size = p_filter->output.i_bytes_per_frame
00285 * p_filter->output.i_rate
00286 / p_filter->output.i_frame_length;
00287 int i_input_size = p_filter->input.i_bytes_per_frame
00288 * p_filter->input.i_rate
00289 / p_filter->input.i_frame_length;
00290
00291 p_first_alloc->i_bytes_per_sec = __MAX( p_first_alloc->i_bytes_per_sec,
00292 i_output_size );
00293
00294 if ( p_filter->b_in_place )
00295 {
00296 p_first_alloc->i_bytes_per_sec = __MAX(
00297 p_first_alloc->i_bytes_per_sec,
00298 i_input_size );
00299 p_filter->output_alloc.i_alloc_type = AOUT_ALLOC_NONE;
00300 }
00301 else
00302 {
00303
00304 memcpy( &p_filter->output_alloc, p_first_alloc,
00305 sizeof(aout_alloc_t) );
00306 p_first_alloc->i_alloc_type = AOUT_ALLOC_STACK;
00307 p_first_alloc->i_bytes_per_sec = i_input_size;
00308 }
00309 }
00310 }
00311
00312
00313
00314
00315 void aout_FiltersPlay( aout_instance_t * p_aout,
00316 aout_filter_t ** pp_filters,
00317 int i_nb_filters, aout_buffer_t ** pp_input_buffer )
00318 {
00319 int i;
00320
00321 for ( i = 0; i < i_nb_filters; i++ )
00322 {
00323 aout_filter_t * p_filter = pp_filters[i];
00324 aout_buffer_t * p_output_buffer;
00325
00326
00327
00328
00329 aout_BufferAlloc( &p_filter->output_alloc,
00330 ((mtime_t)(*pp_input_buffer)->i_nb_samples + 2)
00331 * 1000000 / p_filter->input.i_rate,
00332 *pp_input_buffer, p_output_buffer );
00333 if ( p_output_buffer == NULL )
00334 {
00335 msg_Err( p_aout, "out of memory" );
00336 return;
00337 }
00338
00339
00340
00341 p_filter->pf_do_work( p_aout, p_filter, *pp_input_buffer,
00342 p_output_buffer );
00343
00344 if ( !p_filter->b_in_place )
00345 {
00346 aout_BufferFree( *pp_input_buffer );
00347 *pp_input_buffer = p_output_buffer;
00348 }
00349 }
00350 }
00351