Changeset 036c9c52326be9a14c439ffe5b7e04861779a31d

Show
Ignore:
Timestamp:
09/25/05 18:49:40 (3 years ago)
Author:
Boris Dorès <babal@videolan.org>
git-committer:
Boris Dorès <babal@videolan.org> 1127666980 +0000
git-parent:

[880f95fd6fd6cbeeb9734f0ab72bc4d77b84b273]

git-author:
Boris Dorès <babal@videolan.org> 1127666980 +0000
Message:

- the creation of the audio filter pipeline when specifying user audio

channel mixers was broken (again) in 0.8.1 and 0.8.2; hopefully this
will fix it for good, by allowing audio filters to request a specific
format rather than imposing them an arbitrary one

- various other small fixes in the audio output core
- option to force detection of Dolby Surround
- simple module to decode Dolby Surround
- increase spatialization with two center speakers and fix channel

order for 7.1 streams in the headphone channel mixer

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • configure.ac

    rb1e57e2 r036c9c5  
    10161016  VLC_ADD_PLUGINS([aout_file linear_resampler bandlimited_resampler]) 
    10171017  VLC_ADD_PLUGINS([float32_mixer spdif_mixer simple_channel_mixer]) 
    1018   VLC_ADD_PLUGINS([headphone_channel_mixer normvol equalizer]) 
     1018  VLC_ADD_PLUGINS([dolby_surround_decoder headphone_channel_mixer normvol equalizer]) 
    10191019  VLC_ADD_PLUGINS([fixed32tofloat32 float32tos16 float32tos8 float32tou16 float32tou8 a52tospdif dtstospdif s16tofloat32 s16tofloat32swab s8tofloat32 u8tofloat32 audio_format]) 
    10201020fi 
  • modules/LIST

    rfb4297b r036c9c5  
    110110 * dmo: a DirectMediaObject decoder that uses DirectMedia to decode video (WMV3) 
    111111 
     112 * dolby_surround_decoder: simple decoder for dolby surround encoded streams 
     113 
    112114 * dshow: DirectShow access plugin for encoding cards under Windows 
    113115 
  • modules/audio_filter/channel_mixer/Modules.am

    r067ebc3 r036c9c5  
    22SOURCES_simple_channel_mixer = simple.c 
    33SOURCES_headphone_channel_mixer = headphone.c 
     4SOURCES_dolby_surround_decoder = dolby.c 
  • modules/audio_filter/channel_mixer/headphone.c

    rfe087a3 r036c9c5  
    33 *               -> gives the feeling of a real room with a simple headphone 
    44 ***************************************************************************** 
    5  * Copyright (C) 2002 the VideoLAN team 
     5 * Copyright (C) 2002-2005 the VideoLAN team 
    66 * $Id$ 
    77 * 
     
    4848#define MODULE_DESCRIPTION N_ ( \ 
    4949     "This effect gives you the feeling that you are standing in a room " \ 
    50      "with a complete 5.1 speaker set when using only a headphone, " \ 
     50     "with a complete 7.1 speaker set when using only a headphone, " \ 
    5151     "providing a more realistic sound experience. It should also be " \ 
    5252     "more comfortable and less tiring when listening to music for " \ 
    5353     "long periods of time.\nIt works with any source format from mono " \ 
    54      "to 5.1.") 
     54     "to 7.1.") 
    5555 
    5656#define HEADPHONE_DIM_TEXT N_("Characteristic dimension") 
     
    185185    /* Number of elementary operations */ 
    186186    p_data->i_nb_atomic_operations = i_nb_channels * 2; 
     187    if ( i_physical_channels & AOUT_CHAN_CENTER ) 
     188    { 
     189        p_data->i_nb_atomic_operations += 2; 
     190    } 
    187191    p_data->p_atomic_operations = malloc ( sizeof(struct atomic_operation_t) 
    188192            * p_data->i_nb_atomic_operations ); 
     
    213217        i_source_channel_offset++; 
    214218    } 
     219    if ( i_physical_channels & AOUT_CHAN_MIDDLELEFT ) 
     220    { 
     221        ComputeChannelOperations ( p_data , i_rate 
     222                , i_next_atomic_operation , i_source_channel_offset 
     223                , -d_x , 0 , 1.5 / i_nb_channels ); 
     224        i_next_atomic_operation += 2; 
     225        i_source_channel_offset++; 
     226    } 
     227    if ( i_physical_channels & AOUT_CHAN_MIDDLERIGHT ) 
     228    { 
     229        ComputeChannelOperations ( p_data , i_rate 
     230                , i_next_atomic_operation , i_source_channel_offset 
     231                , d_x , 0 , 1.5 / i_nb_channels ); 
     232        i_next_atomic_operation += 2; 
     233        i_source_channel_offset++; 
     234    } 
    215235    if ( i_physical_channels & AOUT_CHAN_REARLEFT ) 
    216236    { 
     
    239259    if ( i_physical_channels & AOUT_CHAN_CENTER ) 
    240260    { 
    241         ComputeChannelOperations ( p_data , i_rate 
    242                 , i_next_atomic_operation , i_source_channel_offset 
    243                 , 0 , d_z , 1.5 / i_nb_channels ); 
     261        /* having two center channels increases the spatialization effect */ 
     262        ComputeChannelOperations ( p_data , i_rate 
     263                , i_next_atomic_operation , i_source_channel_offset 
     264                , d_x / 5.0 , d_z , 0.75 / i_nb_channels ); 
     265        i_next_atomic_operation += 2; 
     266        ComputeChannelOperations ( p_data , i_rate 
     267                , i_next_atomic_operation , i_source_channel_offset 
     268                , -d_x / 5.0 , d_z , 0.75 / i_nb_channels ); 
    244269        i_next_atomic_operation += 2; 
    245270        i_source_channel_offset++; 
     
    250275                , i_next_atomic_operation , i_source_channel_offset 
    251276                , 0 , d_z_rear , 5.0 / i_nb_channels ); 
    252         i_next_atomic_operation += 2; 
    253         i_source_channel_offset++; 
    254     } 
    255     if ( i_physical_channels & AOUT_CHAN_MIDDLELEFT ) 
    256     { 
    257         ComputeChannelOperations ( p_data , i_rate 
    258                 , i_next_atomic_operation , i_source_channel_offset 
    259                 , -d_x , 0 , 1.5 / i_nb_channels ); 
    260         i_next_atomic_operation += 2; 
    261         i_source_channel_offset++; 
    262     } 
    263     if ( i_physical_channels & AOUT_CHAN_MIDDLERIGHT ) 
    264     { 
    265         ComputeChannelOperations ( p_data , i_rate 
    266                 , i_next_atomic_operation , i_source_channel_offset 
    267                 , d_x , 0 , 1.5 / i_nb_channels ); 
    268277        i_next_atomic_operation += 2; 
    269278        i_source_channel_offset++; 
     
    302311{ 
    303312    aout_filter_t * p_filter = (aout_filter_t *)p_this; 
    304  
    305     if ( p_filter->output.i_physical_channels != ( AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT ) 
    306           || p_filter->input.i_format != p_filter->output.i_format 
    307           || p_filter->input.i_rate != p_filter->output.i_rate 
    308           || (p_filter->input.i_format != VLC_FOURCC('f','l','3','2') 
    309                && p_filter->input.i_format != VLC_FOURCC('f','i','3','2')) ) 
    310     { 
    311         msg_Dbg( p_filter, "Filter discarded (invalid format)" ); 
    312         return -1; 
     313    vlc_bool_t b_fit = VLC_TRUE; 
     314 
     315    /* Activate this filter only with stereo devices */ 
     316    if ( p_filter->output.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) 
     317          || p_filter->output.i_physical_channels 
     318                != ( p_filter->output.i_original_channels & AOUT_CHAN_PHYSMASK ) 
     319          || p_filter->input.i_physical_channels 
     320                != ( p_filter->input.i_original_channels & AOUT_CHAN_PHYSMASK ) ) 
     321    { 
     322        msg_Dbg( p_filter, "Filter discarded (incompatible format)" ); 
     323        return VLC_EGENERIC; 
     324    } 
     325 
     326    /* Request a specific format if not already compatible */ 
     327    if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2') 
     328          || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) 
     329    { 
     330        b_fit = VLC_FALSE; 
     331        p_filter->input.i_format = VLC_FOURCC('f','l','3','2'); 
     332        p_filter->output.i_format = VLC_FOURCC('f','l','3','2'); 
     333    } 
     334    if ( p_filter->input.i_rate != p_filter->output.i_rate ) 
     335    { 
     336        b_fit = VLC_FALSE; 
     337        p_filter->input.i_rate = p_filter->output.i_rate; 
     338    } 
     339    if ( p_filter->input.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) 
     340          && ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO ) ) 
     341    { 
     342        b_fit = VLC_FALSE; 
     343        p_filter->input.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | 
     344                                              AOUT_CHAN_CENTER | 
     345                                              AOUT_CHAN_REARLEFT | 
     346                                              AOUT_CHAN_REARRIGHT; 
     347        p_filter->input.i_original_channels = p_filter->input.i_physical_channels; 
     348    } 
     349    if ( ! b_fit ) 
     350    { 
     351        msg_Dbg( p_filter, "Requesting specific format" ); 
     352        return VLC_EGENERIC; 
    313353    } 
    314354 
     
    317357    if ( p_filter->p_sys == NULL ) 
    318358    { 
    319         msg_Err( p_filter, "out of memory" ); 
    320         return -1
     359        msg_Err( p_filter, "Out of memory" ); 
     360        return VLC_EGENERIC
    321361    } 
    322362    p_filter->p_sys->i_overflow_buffer_size = 0; 
     
    330370                ,  p_filter->input.i_rate ) < 0 ) 
    331371    { 
    332         return -1
     372        return VLC_EGENERIC
    333373    } 
    334374 
     
    336376    p_filter->b_in_place = 0; 
    337377 
    338     return 0
     378    return VLC_SUCCESS
    339379} 
    340380 
  • modules/audio_filter/equalizer.c

    rfe087a3 r036c9c5  
    137137    aout_filter_t     *p_filter = (aout_filter_t *)p_this; 
    138138    aout_filter_sys_t *p_sys; 
     139    vlc_bool_t         b_fit = VLC_TRUE; 
    139140 
    140141    if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || 
    141142        p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) 
    142143    { 
     144        b_fit = VLC_FALSE; 
     145        p_filter->input.i_format = VLC_FOURCC('f','l','3','2'); 
     146        p_filter->output.i_format = VLC_FOURCC('f','l','3','2'); 
    143147        msg_Warn( p_filter, "Bad input or output format" ); 
    144         return VLC_EGENERIC; 
    145148    } 
    146149    if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) 
    147150    { 
     151        b_fit = VLC_FALSE; 
     152        memcpy( &p_filter->output, &p_filter->input, 
     153                sizeof(audio_sample_format_t) ); 
    148154        msg_Warn( p_filter, "input and output formats are not similar" ); 
     155    } 
     156 
     157    if ( ! b_fit ) 
     158    { 
    149159        return VLC_EGENERIC; 
    150160    } 
  • modules/audio_filter/normvol.c

    rfe087a3 r036c9c5  
    9999{ 
    100100    aout_filter_t *p_filter = (aout_filter_t*)p_this; 
     101    vlc_bool_t b_fit = VLC_TRUE; 
    101102    int i_channels; 
    102103    aout_filter_sys_t *p_sys = p_filter->p_sys = 
     
    106107        p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) 
    107108    { 
    108             msg_Warn( p_filter, "Bad input or output format" ); 
    109             return VLC_EGENERIC; 
     109        b_fit = VLC_FALSE; 
     110        p_filter->input.i_format = VLC_FOURCC('f','l','3','2'); 
     111        p_filter->output.i_format = VLC_FOURCC('f','l','3','2'); 
     112        msg_Warn( p_filter, "Bad input or output format" ); 
    110113    } 
    111114 
    112115    if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) 
    113116    { 
     117        b_fit = VLC_FALSE; 
     118        memcpy( &p_filter->output, &p_filter->input, 
     119                sizeof(audio_sample_format_t) ); 
    114120        msg_Warn( p_filter, "input and output formats are not similar" ); 
     121    } 
     122 
     123    if ( ! b_fit ) 
     124    { 
    115125        return VLC_EGENERIC; 
    116126    } 
  • modules/gui/macosx/extended.m

    rfd323ab r036c9c5  
    367367    if ([o_ckb_hdphnVirt state] == NSOnState) 
    368368    { 
    369         [self changeAFiltersString: "headphone" onOrOff: VLC_TRUE ]; 
     369        [self changeAFiltersString: "headphone_channel_mixer" onOrOff: VLC_TRUE ]; 
    370370    }else{ 
    371         [self changeAFiltersString: "headphone" onOrOff: VLC_FALSE ]; 
     371        [self changeAFiltersString: "headphone_channel_mixer" onOrOff: VLC_FALSE ]; 
    372372    } 
    373373} 
  • modules/gui/wxwidgets/extrapanel.cpp

    r6ea5cf5 r036c9c5  
    820820    aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf, 
    821821                                 VLC_OBJECT_AOUT, FIND_ANYWHERE); 
    822     ChangeFiltersString( p_intf , p_aout, "headphone", 
     822    ChangeFiltersString( p_intf , p_aout, "headphone_channel_mixer", 
    823823                         event.IsChecked() ? VLC_TRUE : VLC_FALSE ); 
    824824    if( p_aout != NULL ) 
  • src/audio_output/filters.c

    rfe087a3 r036c9c5  
    117117} 
    118118 
     119static void ReleaseFilter( aout_filter_t * p_filter ) 
     120{ 
     121    module_Unneed( p_filter, p_filter->p_module ); 
     122    vlc_object_detach( p_filter ); 
     123    vlc_object_destroy( p_filter ); 
     124} 
     125 
    119126/***************************************************************************** 
    120127 * aout_FiltersCreatePipeline: create a filters pipeline to transform a sample 
    121128 *                             format to another 
    122129 ***************************************************************************** 
    123  * TODO : allow the user to add/remove specific filters 
     130 * pi_nb_filters must be initialized before calling this function 
    124131 *****************************************************************************/ 
    125132int aout_FiltersCreatePipeline( aout_instance_t * p_aout, 
    126                                 aout_filter_t ** pp_filters
     133                                aout_filter_t ** pp_filters_start
    127134                                int * pi_nb_filters, 
    128135                                const audio_sample_format_t * p_input_format, 
    129136                                const audio_sample_format_t * p_output_format ) 
    130137{ 
     138    aout_filter_t** pp_filters = pp_filters_start + *pi_nb_filters; 
    131139    audio_sample_format_t temp_format; 
    132140    int i_nb_conversions; 
     
    135143    { 
    136144        msg_Dbg( p_aout, "no need for any filter" ); 
    137         *pi_nb_filters = 0; 
    138145        return 0; 
    139146    } 
    140147 
    141148    aout_FormatsPrint( p_aout, "filter(s)", p_input_format, p_output_format ); 
     149 
     150    if( *pi_nb_filters + 1 > AOUT_MAX_FILTERS ) 
     151    { 
     152        msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS ); 
     153        return -1; 
     154    } 
    142155 
    143156    /* Try to find a filter to do the whole conversion. */ 
     
    146159    { 
    147160        msg_Dbg( p_aout, "found a filter for the whole conversion" ); 
    148         *pi_nb_filters = 1
     161        ++*pi_nb_filters
    149162        return 0; 
    150163    } 
     
    178191    /* We have the first stage of the conversion. Find a filter for 
    179192     * the rest. */ 
     193    if( *pi_nb_filters + 2 > AOUT_MAX_FILTERS ) 
     194    { 
     195        ReleaseFilter( pp_filters[0] ); 
     196        msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS ); 
     197        return -1; 
     198    } 
    180199    pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, 
    181200                                p_output_format ); 
     
    187206        if ( !i_nb_conversions ) 
    188207        { 
    189             vlc_object_detach( pp_filters[0] ); 
    190             vlc_object_destroy( pp_filters[0] ); 
     208            ReleaseFilter( pp_filters[0] ); 
    191209            msg_Err( p_aout, 
    192210              "couldn't find a filter for the second part of the conversion" ); 
     211            return -1; 
     212        } 
     213        if( *pi_nb_filters + 3 > AOUT_MAX_FILTERS ) 
     214        { 
     215            ReleaseFilter( pp_filters[0] ); 
     216            msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS ); 
     217            return -1; 
    193218        } 
    194219        pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, 
     
    199224        if ( pp_filters[1] == NULL || pp_filters[2] == NULL ) 
    200225        { 
    201             vlc_object_detach( pp_filters[0] ); 
    202             vlc_object_destroy( pp_filters[0] ); 
     226            ReleaseFilter( pp_filters[0] ); 
    203227            if ( pp_filters[1] != NULL ) 
    204228            { 
    205                 vlc_object_detach( pp_filters[1] ); 
    206                 vlc_object_destroy( pp_filters[1] ); 
     229                ReleaseFilter( pp_filters[1] ); 
    207230            } 
    208231            if ( pp_filters[2] != NULL ) 
    209232            { 
    210                 vlc_object_detach( pp_filters[2] ); 
    211                 vlc_object_destroy( pp_filters[2] ); 
     233                ReleaseFilter( pp_filters[2] ); 
    212234            } 
    213235            msg_Err( p_aout, 
    214236               "couldn't find filters for the second part of the conversion" ); 
    215         } 
    216         *pi_nb_filters = 3; 
     237            return -1; 
     238        } 
     239        *pi_nb_filters += 3; 
     240        msg_Dbg( p_aout, "found 3 filters for the whole conversion" ); 
    217241    } 
    218242    else 
    219243    { 
    220         *pi_nb_filters = 2; 
    221     } 
    222  
    223     /* We have enough filters. */ 
    224     msg_Dbg( p_aout, "found %d filters for the whole conversion", 
    225              *pi_nb_filters ); 
     244        *pi_nb_filters += 2; 
     245        msg_Dbg( p_aout, "found 2 filters for the whole conversion" ); 
     246    } 
     247 
    226248    return 0; 
    227249} 
  • src/audio_output/input.c

    r2b6826a r036c9c5  
    3838#include "aout_internal.h" 
    3939 
     40static void inputFailure( aout_instance_t *, aout_input_t *, char * ); 
    4041static int VisualizationCallback( vlc_object_t *, char const *, 
    4142                                  vlc_value_t, vlc_value_t, void * ); 
    4243static int EqualizerCallback( vlc_object_t *, char const *, 
    4344                              vlc_value_t, vlc_value_t, void * ); 
    44 static aout_filter_t * allocateUserChannelMixer( aout_instance_t *, 
    45                                                  audio_sample_format_t *, 
    46                                                  audio_sample_format_t * ); 
    4745 
    4846/***************************************************************************** 
     
    5149int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) 
    5250{ 
    53     audio_sample_format_t user_filter_format; 
    54     audio_sample_format_t intermediate_format;/* input of resampler */ 
     51    audio_sample_format_t chain_input_format; 
     52    audio_sample_format_t chain_output_format; 
    5553    vlc_value_t val, text; 
    5654    char * psz_filters, *psz_visual; 
    57     aout_filter_t * p_user_channel_mixer; 
    5855 
    5956    aout_FormatPrint( p_aout, "input", &p_input->input ); 
     57 
     58    p_input->i_nb_filters = 0; 
    6059 
    6160    /* Prepare FIFO. */ 
     
    6463 
    6564    /* Prepare format structure */ 
    66     memcpy( &intermediate_format, &p_aout->mixer.mixer
     65    memcpy( &chain_input_format, &p_input->input
    6766            sizeof(audio_sample_format_t) ); 
    68     intermediate_format.i_rate = p_input->input.i_rate; 
    69  
    70     /* Try to use the channel mixer chosen by the user */ 
    71     memcpy ( &user_filter_format, &intermediate_format, 
    72              sizeof(audio_sample_format_t) ); 
    73     user_filter_format.i_physical_channels = p_input->input.i_physical_channels; 
    74     user_filter_format.i_original_channels = p_input->input.i_original_channels; 
    75     user_filter_format.i_bytes_per_frame = user_filter_format.i_bytes_per_frame 
    76                               * aout_FormatNbChannels( &user_filter_format ) 
    77                               / aout_FormatNbChannels( &intermediate_format ); 
    78     p_user_channel_mixer = allocateUserChannelMixer( p_aout, &user_filter_format, 
    79                                                    &intermediate_format ); 
    80     /* If it failed, let the main pipeline do channel mixing */ 
    81     if ( ! p_user_channel_mixer ) 
    82     { 
    83         memcpy ( &user_filter_format, &intermediate_format, 
    84                  sizeof(audio_sample_format_t) ); 
    85     } 
    86  
    87     /* Create filters. */ 
    88     if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, 
    89                                      &p_input->i_nb_filters, 
    90                                      &p_input->input, 
    91                                      &user_filter_format 
    92                                      ) < 0 ) 
    93     { 
    94         msg_Err( p_aout, "couldn't set an input pipeline" ); 
    95  
    96         aout_FifoDestroy( p_aout, &p_input->fifo ); 
    97         p_input->b_error = 1; 
    98         return -1; 
    99     } 
     67    memcpy( &chain_output_format, &p_aout->mixer.mixer, 
     68            sizeof(audio_sample_format_t) ); 
     69    chain_output_format.i_rate = p_input->input.i_rate; 
     70    aout_FormatPrepare( &chain_output_format ); 
    10071 
    10172    /* Now add user filters */ 
     
    199170    } 
    200171 
     172    /* parse user filter list */ 
    201173    if( psz_filters && *psz_filters ) 
    202174    { 
     
    205177        while( psz_parser && *psz_parser ) 
    206178        { 
    207             aout_filter_t * p_filter
     179            aout_filter_t * p_filter = NULL
    208180 
    209181            if( p_input->i_nb_filters >= AOUT_MAX_FILTERS ) 
     
    225197                break; 
    226198            } 
    227  
    228             msg_Dbg( p_aout, "user filter \"%s\"", psz_parser ); 
    229199 
    230200            /* Create a VLC object */ 
     
    239209 
    240210            vlc_object_attach( p_filter , p_aout ); 
    241             memcpy( &p_filter->input, &user_filter_format, 
     211 
     212            /* request format */ 
     213            memcpy( &p_filter->input, &chain_input_format, 
    242214                    sizeof(audio_sample_format_t) ); 
    243             memcpy( &p_filter->output, &user_filter_format, 
     215            memcpy( &p_filter->output, &chain_output_format, 
    244216                    sizeof(audio_sample_format_t) ); 
    245217 
    246             p_filter->p_module = 
    247                 module_Need( p_filter,"audio filter", psz_parser, VLC_FALSE ); 
    248  
    249             if( p_filter->p_module== NULL ) 
    250             { 
    251                 p_filter->p_module = 
    252                     module_Need( p_filter,"visualization", psz_parser, 
    253                                                            VLC_FALSE ); 
    254                 if( p_filter->p_module == NULL ) 
     218            /* try to find the requested filter */ 
     219            p_filter->p_module = module_Need( p_filter, "audio filter", 
     220                                              psz_parser, VLC_TRUE ); 
     221 
     222            if ( p_filter->p_module == NULL ) 
     223            { 
     224                /* if the filter requested a special format, retry */ 
     225                if ( !( AOUT_FMTS_IDENTICAL( &p_filter->input, 
     226                                             &chain_input_format ) 
     227                        && AOUT_FMTS_IDENTICAL( &p_filter->output, 
     228                                                &chain_output_format ) ) ) 
     229                { 
     230                    aout_FormatPrepare( &p_filter->input ); 
     231                    aout_FormatPrepare( &p_filter->output ); 
     232                    p_filter->p_module = module_Need( p_filter, "audio filter", 
     233                                                      psz_parser, VLC_TRUE ); 
     234                } 
     235                /* try visual filters */ 
     236                else 
     237                { 
     238                    memcpy( &p_filter->input, &chain_output_format, 
     239                            sizeof(audio_sample_format_t) ); 
     240                    memcpy( &p_filter->output, &chain_output_format, 
     241                            sizeof(audio_sample_format_t) ); 
     242                    p_filter->p_module = module_Need( p_filter, "visualization", 
     243                                                      psz_parser, VLC_TRUE ); 
     244                } 
     245            } 
     246 
     247            /* failure */ 
     248            if ( p_filter->p_module == NULL ) 
     249            { 
     250                msg_Err( p_aout, "cannot add user filter %s (skipped)", 
     251                         psz_parser ); 
     252 
     253                vlc_object_detach( p_filter ); 
     254                vlc_object_destroy( p_filter ); 
     255 
     256                psz_parser = psz_next; 
     257                continue; 
     258            } 
     259 
     260            /* complete the filter chain if necessary */ 
     261            if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &p_filter->input ) ) 
     262            { 
     263                if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, 
     264                                                 &p_input->i_nb_filters, 
     265                                                 &chain_input_format, 
     266                                                 &p_filter->input ) < 0 ) 
    255267                { 
    256268                    msg_Err( p_aout, "cannot add user filter %s (skipped)", 
    257269                             psz_parser ); 
    258270 
     271                    module_Unneed( p_filter, p_filter->p_module ); 
    259272                    vlc_object_detach( p_filter ); 
    260273                    vlc_object_destroy( p_filter ); 
     274 
    261275                    psz_parser = psz_next; 
    262276                    continue; 
    263277                } 
    264278            } 
     279 
     280            /* success */ 
    265281            p_filter->b_continuity = VLC_FALSE; 
    266  
    267282            p_input->pp_filters[p_input->i_nb_filters++] = p_filter; 
     283            memcpy( &chain_input_format, &p_filter->output, 
     284                    sizeof( audio_sample_format_t ) ); 
    268285 
    269286            /* next filter if any */ 
     
    274291    if( psz_visual ) free( psz_visual ); 
    275292 
    276     /* Attach the user channel mixer */ 
    277     if ( p_user_channel_mixer ) 
    278     { 
    279         p_input->pp_filters[p_input->i_nb_filters++] = p_user_channel_mixer; 
     293    /* complete the filter chain if necessary */ 
     294    if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &chain_output_format ) ) 
     295    { 
     296        if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, 
     297                                         &p_input->i_nb_filters, 
     298                                         &chain_input_format, 
     299                                         &chain_output_format ) < 0 ) 
     300        { 
     301            inputFailure( p_aout, p_input, "couldn't set an input pipeline" ); 
     302            return -1; 
     303        } 
    280304    } 
    281305 
     
    284308    p_input->input_alloc.i_bytes_per_sec = -1; 
    285309 
     310    /* Create resamplers. */ 
    286311    if ( AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) ) 
    287312    { 
     
    290315    else 
    291316    { 
    292         /* Create resamplers. */ 
    293         intermediate_format.i_rate = (__MAX(p_input->input.i_rate, 
     317        chain_output_format.i_rate = (__MAX(p_input->input.i_rate, 
    294318                                            p_aout->mixer.mixer.i_rate) 
    295319                                 * (100 + AOUT_MAX_RESAMPLING)) / 100; 
    296         if ( intermediate_format.i_rate == p_aout->mixer.mixer.i_rate ) 
     320        if ( chain_output_format.i_rate == p_aout->mixer.mixer.i_rate ) 
    297321        { 
    298322            /* Just in case... */ 
    299             intermediate_format.i_rate++; 
    300         } 
     323            chain_output_format.i_rate++; 
     324        } 
     325        p_input->i_nb_resamplers = 0; 
    301326        if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers, 
    302327                                         &p_input->i_nb_resamplers, 
    303                                          &intermediate_format, 
     328                                         &chain_output_format, 
    304329                                         &p_aout->mixer.mixer ) < 0 ) 
    305330        { 
    306             msg_Err( p_aout, "couldn't set a resampler pipeline" ); 
    307  
    308             aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, 
    309                                          p_input->i_nb_filters ); 
    310             aout_FifoDestroy( p_aout, &p_input->fifo ); 
    311             var_Destroy( p_aout, "visual" ); 
    312             p_input->b_error = 1; 
    313  
     331            inputFailure( p_aout, p_input, "couldn't set a resampler pipeline"); 
    314332            return -1; 
    315333        } 
     
    318336                                 p_input->i_nb_resamplers, 
    319337                                 &p_input->input_alloc ); 
     338        p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; 
    320339 
    321340        /* Setup the initial rate of the resampler */ 
     
    324343    p_input->i_resampling_type = AOUT_RESAMPLING_NONE; 
    325344 
    326     p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; 
    327345    aout_FiltersHintBuffers( p_aout, p_input->pp_filters, 
    328346                             p_input->i_nb_filters, 
    329347                             &p_input->input_alloc ); 
     348    p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; 
    330349 
    331350    /* i_bytes_per_sec is still == -1 if no filters */ 
     
    335354                                     * p_input->input.i_rate 
    336355                                     / p_input->input.i_frame_length) ); 
    337     /* Allocate in the heap, it is more convenient for the decoder. */ 
    338     p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; 
    339  
     356 
     357    /* Success */ 
    340358    p_input->b_error = VLC_FALSE; 
    341359    p_input->b_restart = VLC_FALSE; 
     
    355373    aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, 
    356374                                 p_input->i_nb_filters ); 
     375    p_input->i_nb_filters = 0; 
    357376    aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers, 
    358377                                 p_input->i_nb_resamplers ); 
     378    p_input->i_nb_resamplers = 0; 
    359379    aout_FifoDestroy( p_aout, &p_input->fifo ); 
    360380 
     
    573593} 
    574594 
    575 static int ChangeFiltersString( aout_instance_t * p_aout, 
     595/***************************************************************************** 
     596 * static functions 
     597 *****************************************************************************/ 
     598 
     599static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input, 
     600                          char * psz_error_message ) 
     601
     602    /* error message */ 
     603    msg_Err( p_aout, "couldn't set an input pipeline" ); 
     604 
     605    /* clean up */ 
     606    aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, 
     607                                 p_input->i_nb_filters ); 
     608    aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers, 
     609                                 p_input->i_nb_resamplers ); 
     610    aout_FifoDestroy( p_aout, &p_input->fifo ); 
     611    var_Destroy( p_aout, "visual" ); 
     612    var_Destroy( p_aout, "equalizer" ); 
     613    var_Destroy( p_aout, "audio-filter" ); 
     614    var_Destroy( p_aout, "audio-visual" ); 
     615 
     616    /* error flag */ 
     617    p_input->b_error = 1; 
     618
     619 
     620static int ChangeFiltersString( aout_instance_t * p_aout, char* psz_variable, 
    576621                                 char *psz_name, vlc_bool_t b_add ) 
    577622{ 
     
    579624    char *psz_parser; 
    580625 
    581     var_Get( p_aout, "audio-filter", &val ); 
     626    var_Get( p_aout, psz_variable, &val ); 
    582627 
    583628    if( !val.psz_string ) val.psz_string = strdup(""); 
     
    614659    } 
    615660 
    616     var_Set( p_aout, "audio-filter", val ); 
     661    var_Set( p_aout, psz_variable, val ); 
    617662    free( val.psz_string ); 
    618663    return 1; 
     
    629674    if( !psz_mode || !*psz_mode ) 
    630675    { 
    631         ChangeFiltersString( p_aout, "goom", VLC_FALSE ); 
    632         ChangeFiltersString( p_aout, "visual", VLC_FALSE ); 
    633         ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); 
     676        ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_FALSE ); 
     677        ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_FALSE ); 
     678        ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_FALSE ); 
    634679    } 
    635680    else 
     
    637682        if( !strcmp( "goom", psz_mode ) ) 
    638683        { 
    639             ChangeFiltersString( p_aout, "visual", VLC_FALSE ); 
    640             ChangeFiltersString( p_aout, "goom", VLC_TRUE ); 
    641             ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); 
     684            ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_FALSE ); 
     685            ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_TRUE ); 
     686            ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_FALSE); 
    642687        } 
    643688        else if( !strcmp( "galaktos", psz_mode ) ) 
    644689        { 
    645             ChangeFiltersString( p_aout, "visual", VLC_FALSE ); 
    646             ChangeFiltersString( p_aout, "goom", VLC_FALSE ); 
    647             ChangeFiltersString( p_aout, "galaktos", VLC_TRUE ); 
     690            ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_FALSE ); 
     691            ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_FALSE ); 
     692            ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_TRUE ); 
    648693        } 
    649694        else 
     
    653698            var_Set( p_aout, "effect-list", val ); 
    654699 
    655             ChangeFiltersString( p_aout, "goom", VLC_FALSE ); 
    656             ChangeFiltersString( p_aout, "visual", VLC_TRUE ); 
    657             ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); 
     700            ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_FALSE ); 
     701            ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_TRUE ); 
     702            ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_FALSE); 
    658703        } 
    659704    } 
     
    679724    if( !psz_mode || !*psz_mode ) 
    680725    { 
    681         i_ret = ChangeFiltersString( p_aout, "equalizer", VLC_FALSE ); 
     726        i_ret = ChangeFiltersString( p_aout, "audio-filter", "equalizer", 
     727                                     VLC_FALSE ); 
    682728    } 
    683729    else 
     
    686732        var_Create( p_aout, "equalizer-preset", VLC_VAR_STRING ); 
    687733        var_Set( p_aout, "equalizer-preset", val ); 
    688         i_ret = ChangeFiltersString( p_aout, "equalizer", VLC_TRUE ); 
     734        i_ret = ChangeFiltersString( p_aout, "audio-filter", "equalizer", 
     735                                     VLC_TRUE ); 
    689736 
    690737    } 
     
    701748    return VLC_SUCCESS; 
    702749} 
    703  
    704 static aout_filter_t * allocateUserChannelMixer( aout_instance_t * p_aout, 
    705                                      audio_sample_format_t * p_input_format, 
    706                                      audio_sample_format_t * p_output_format ) 
    707 { 
    708     aout_filter_t * p_channel_mixer; 
    709  
    710     /* Retreive user preferred channel mixer */ 
    711     char * psz_name = config_GetPsz( p_aout, "audio-channel-mixer" ); 
    712  
    713     /* Not specified => let the main pipeline do the mixing */ 
    714     if ( ! psz_name ) return NULL; 
    715  
    716     /* Debug information */ 
    717     aout_FormatsPrint( p_aout, "channel mixer", p_input_format, 
    718                        p_output_format ); 
    719  
    720     /* Create a VLC object */ 
    721     p_channel_mixer = vlc_object_create( p_aout, sizeof(aout_filter_t) ); 
    722     if( p_channel_mixer == NULL ) 
    723     { 
    724         msg_Err( p_aout, "cannot add user channel mixer %s", psz_name ); 
    725         return NULL; 
    726     } 
    727     vlc_object_attach( p_channel_mixer , p_aout ); 
    728  
    729     /* Attach the suitable module */ 
    730     memcpy( &p_channel_mixer->input, p_input_format, 
    731                     sizeof(audio_sample_format_t) ); 
    732     memcpy( &p_channel_mixer->output, p_output_format, 
    733                     sizeof(audio_sample_format_t) ); 
    734     p_