From: Boris Dorès Date: Sun, 25 Sep 2005 16:49:40 +0000 (+0000) Subject: - the creation of the audio filter pipeline when specifying user audio X-Git-Tag: 0.8.4~415 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=036c9c52326be9a14c439ffe5b7e04861779a31d;p=vlc - 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 --- diff --git a/configure.ac b/configure.ac index 1502e7d0c8..5680ef4e49 100644 --- a/configure.ac +++ b/configure.ac @@ -1015,7 +1015,7 @@ dnl VLC_ADD_PLUGINS([externrun]) VLC_ADD_PLUGINS([i420_yuy2 i422_yuy2 i420_ymga]) VLC_ADD_PLUGINS([aout_file linear_resampler bandlimited_resampler]) VLC_ADD_PLUGINS([float32_mixer spdif_mixer simple_channel_mixer]) - VLC_ADD_PLUGINS([headphone_channel_mixer normvol equalizer]) + VLC_ADD_PLUGINS([dolby_surround_decoder headphone_channel_mixer normvol equalizer]) VLC_ADD_PLUGINS([fixed32tofloat32 float32tos16 float32tos8 float32tou16 float32tou8 a52tospdif dtstospdif s16tofloat32 s16tofloat32swab s8tofloat32 u8tofloat32 audio_format]) fi diff --git a/modules/LIST b/modules/LIST index 9cf04079c7..17c597bfb9 100644 --- a/modules/LIST +++ b/modules/LIST @@ -109,6 +109,8 @@ $Id$ * dmo: a DirectMediaObject decoder that uses DirectMedia to decode video (WMV3) + * dolby_surround_decoder: simple decoder for dolby surround encoded streams + * dshow: DirectShow access plugin for encoding cards under Windows * dts: DTS basic parser/packetizer diff --git a/modules/audio_filter/channel_mixer/Modules.am b/modules/audio_filter/channel_mixer/Modules.am index 7278b0548d..11f45dd96a 100644 --- a/modules/audio_filter/channel_mixer/Modules.am +++ b/modules/audio_filter/channel_mixer/Modules.am @@ -1,3 +1,4 @@ SOURCES_trivial_channel_mixer = trivial.c SOURCES_simple_channel_mixer = simple.c SOURCES_headphone_channel_mixer = headphone.c +SOURCES_dolby_surround_decoder = dolby.c diff --git a/modules/audio_filter/channel_mixer/dolby.c b/modules/audio_filter/channel_mixer/dolby.c new file mode 100644 index 0000000000..797f53d764 --- /dev/null +++ b/modules/audio_filter/channel_mixer/dolby.c @@ -0,0 +1,242 @@ +/***************************************************************************** + * dolby.c : simple decoder for dolby surround encoded streams + ***************************************************************************** + * Copyright (C) 2005 the VideoLAN team + * $Id: headphone.c 11664 2005-07-09 06:17:09Z courmisch $ + * + * Authors: Boris Dorès + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include /* malloc(), free() */ +#include + +#include +#include "audio_output.h" +#include "aout_internal.h" + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int Create ( vlc_object_t * ); +static void Destroy ( vlc_object_t * ); + +static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, + aout_buffer_t * ); + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +vlc_module_begin(); + set_description( N_("Simple decoder for dolby surround encoded streams") ); + set_shortname( _("Dolby surround decoder") ); + set_category( CAT_INPUT ); + set_subcategory( SUBCAT_INPUT_ACODEC ); + set_capability( "audio filter", 5 ); + set_callbacks( Create, Destroy ); +vlc_module_end(); + +/***************************************************************************** + * Internal data structures + *****************************************************************************/ +struct aout_filter_sys_t +{ + int i_left; + int i_center; + int i_right; + int i_rear_left; + int i_rear_center; + int i_rear_right; +}; + +/* our internal channel order (WG-4 order) */ +static const uint32_t pi_channels[] = +{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, + AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER, + AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 }; + +/***************************************************************************** + * Create: allocate headphone downmixer + *****************************************************************************/ +static int Create( vlc_object_t *p_this ) +{ + int i = 0; + int i_offset = 0; + aout_filter_t * p_filter = (aout_filter_t *)p_this; + + /* Validate audio filter format */ + if ( p_filter->input.i_original_channels + != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT|AOUT_CHAN_DOLBYSTEREO ) + || aout_FormatNbChannels( &p_filter->output ) <= 2 + || p_filter->output.i_physical_channels + != ( p_filter->output.i_original_channels & AOUT_CHAN_PHYSMASK ) + || p_filter->input.i_physical_channels + != ( p_filter->input.i_original_channels & AOUT_CHAN_PHYSMASK )) + { + return VLC_EGENERIC; + } + + if ( p_filter->input.i_rate != p_filter->output.i_rate ) + { + return VLC_EGENERIC; + } + + if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2') + || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) + { + return VLC_EGENERIC; + } + + /* Allocate the memory needed to store the module's structure */ + p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) ); + if ( p_filter->p_sys == NULL ) + { + msg_Err( p_filter, "Out of memory" ); + return VLC_EGENERIC; + } + p_filter->p_sys->i_left = -1; + p_filter->p_sys->i_center = -1; + p_filter->p_sys->i_right = -1; + p_filter->p_sys->i_rear_left = -1; + p_filter->p_sys->i_rear_center = -1; + p_filter->p_sys->i_rear_right = -1; + + while ( pi_channels[i] ) + { + if ( p_filter->output.i_physical_channels & pi_channels[i] ) + { + switch ( pi_channels[i] ) + { + case AOUT_CHAN_LEFT: + p_filter->p_sys->i_left = i_offset; + break; + case AOUT_CHAN_CENTER: + p_filter->p_sys->i_center = i_offset; + break; + case AOUT_CHAN_RIGHT: + p_filter->p_sys->i_right = i_offset; + break; + case AOUT_CHAN_REARLEFT: + p_filter->p_sys->i_rear_left = i_offset; + break; + case AOUT_CHAN_REARCENTER: + p_filter->p_sys->i_rear_center = i_offset; + break; + case AOUT_CHAN_REARRIGHT: + p_filter->p_sys->i_rear_right = i_offset; + break; + } + ++i_offset; + } + ++i; + } + + p_filter->pf_do_work = DoWork; + p_filter->b_in_place = 0; + + return VLC_SUCCESS; +} + +/***************************************************************************** + * Destroy: deallocate resources associated with headphone downmixer + *****************************************************************************/ +static void Destroy( vlc_object_t *p_this ) +{ + aout_filter_t * p_filter = (aout_filter_t *)p_this; + + if ( p_filter->p_sys != NULL ) + { + free ( p_filter->p_sys ); + p_filter->p_sys = NULL; + } +} + +/***************************************************************************** + * DoWork: convert a buffer + *****************************************************************************/ +static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, + aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf ) +{ + float * p_in = (float*) p_in_buf->p_buffer; + float * p_out = (float*) p_out_buf->p_buffer; + size_t i_nb_samples = p_in_buf->i_nb_samples; + size_t i_nb_channels = aout_FormatNbChannels( &p_filter->output ); + + p_out_buf->i_nb_samples = i_nb_samples; + p_out_buf->i_nb_bytes = sizeof(float) * i_nb_samples + * aout_FormatNbChannels( &p_filter->output ); + memset ( p_out , 0 , p_out_buf->i_nb_bytes ); + + if ( p_filter->p_sys != NULL ) + { + struct aout_filter_sys_t * p_sys = p_filter->p_sys; + size_t i_nb_rear = 0; + size_t i; + + if ( p_sys->i_rear_left >= 0 ) + { + ++i_nb_rear; + } + if ( p_sys->i_rear_center >= 0 ) + { + ++i_nb_rear; + } + if ( p_sys->i_rear_right >= 0 ) + { + ++i_nb_rear; + } + + for ( i = 0; i < i_nb_samples; ++i ) + { + float f_left = p_in[ i * 2 ]; + float f_right = p_in[ i * 2 + 1 ]; + float f_rear = ( f_left - f_right ) / i_nb_rear; + + if ( p_sys->i_center >= 0 ) + { + float f_center = f_left + f_right; + f_left -= f_center / 2; + f_right -= f_center / 2; + + p_out[ i * i_nb_channels + p_sys->i_center ] = f_center; + } + + if ( p_sys->i_left >= 0 ) + { + p_out[ i * i_nb_channels + p_sys->i_left ] = f_left; + } + if ( p_sys->i_right >= 0 ) + { + p_out[ i * i_nb_channels + p_sys->i_right ] = f_right; + } + if ( p_sys->i_rear_left >= 0 ) + { + p_out[ i * i_nb_channels + p_sys->i_rear_left ] = f_rear; + } + if ( p_sys->i_rear_center >= 0 ) + { + p_out[ i * i_nb_channels + p_sys->i_rear_center ] = f_rear; + } + if ( p_sys->i_rear_right >= 0 ) + { + p_out[ i * i_nb_channels + p_sys->i_rear_right ] = f_rear; + } + } + } +} diff --git a/modules/audio_filter/channel_mixer/headphone.c b/modules/audio_filter/channel_mixer/headphone.c index d6b07afc46..7949b4110c 100644 --- a/modules/audio_filter/channel_mixer/headphone.c +++ b/modules/audio_filter/channel_mixer/headphone.c @@ -2,7 +2,7 @@ * headphone.c : headphone virtual spatialization channel mixer module * -> gives the feeling of a real room with a simple headphone ***************************************************************************** - * Copyright (C) 2002 the VideoLAN team + * Copyright (C) 2002-2005 the VideoLAN team * $Id$ * * Authors: Boris Dorès @@ -47,11 +47,11 @@ static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, *****************************************************************************/ #define MODULE_DESCRIPTION N_ ( \ "This effect gives you the feeling that you are standing in a room " \ - "with a complete 5.1 speaker set when using only a headphone, " \ + "with a complete 7.1 speaker set when using only a headphone, " \ "providing a more realistic sound experience. It should also be " \ "more comfortable and less tiring when listening to music for " \ "long periods of time.\nIt works with any source format from mono " \ - "to 5.1.") + "to 7.1.") #define HEADPHONE_DIM_TEXT N_("Characteristic dimension") #define HEADPHONE_DIM_LONGTEXT N_( \ @@ -184,6 +184,10 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data /* Number of elementary operations */ p_data->i_nb_atomic_operations = i_nb_channels * 2; + if ( i_physical_channels & AOUT_CHAN_CENTER ) + { + p_data->i_nb_atomic_operations += 2; + } p_data->p_atomic_operations = malloc ( sizeof(struct atomic_operation_t) * p_data->i_nb_atomic_operations ); if ( p_data->p_atomic_operations == NULL ) @@ -212,59 +216,64 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data i_next_atomic_operation += 2; i_source_channel_offset++; } - if ( i_physical_channels & AOUT_CHAN_REARLEFT ) + if ( i_physical_channels & AOUT_CHAN_MIDDLELEFT ) { ComputeChannelOperations ( p_data , i_rate , i_next_atomic_operation , i_source_channel_offset - , -d_x , d_z_rear , 1.5 / i_nb_channels ); + , -d_x , 0 , 1.5 / i_nb_channels ); i_next_atomic_operation += 2; i_source_channel_offset++; } - if ( i_physical_channels & AOUT_CHAN_REARRIGHT ) + if ( i_physical_channels & AOUT_CHAN_MIDDLERIGHT ) { ComputeChannelOperations ( p_data , i_rate , i_next_atomic_operation , i_source_channel_offset - , d_x , d_z_rear , 1.5 / i_nb_channels ); + , d_x , 0 , 1.5 / i_nb_channels ); i_next_atomic_operation += 2; i_source_channel_offset++; } - if ( i_physical_channels & AOUT_CHAN_REARCENTER ) + if ( i_physical_channels & AOUT_CHAN_REARLEFT ) { ComputeChannelOperations ( p_data , i_rate , i_next_atomic_operation , i_source_channel_offset - , 0 , -d_z , 1.5 / i_nb_channels ); + , -d_x , d_z_rear , 1.5 / i_nb_channels ); i_next_atomic_operation += 2; i_source_channel_offset++; } - if ( i_physical_channels & AOUT_CHAN_CENTER ) + if ( i_physical_channels & AOUT_CHAN_REARRIGHT ) { ComputeChannelOperations ( p_data , i_rate , i_next_atomic_operation , i_source_channel_offset - , 0 , d_z , 1.5 / i_nb_channels ); + , d_x , d_z_rear , 1.5 / i_nb_channels ); i_next_atomic_operation += 2; i_source_channel_offset++; } - if ( i_physical_channels & AOUT_CHAN_LFE ) + if ( i_physical_channels & AOUT_CHAN_REARCENTER ) { ComputeChannelOperations ( p_data , i_rate , i_next_atomic_operation , i_source_channel_offset - , 0 , d_z_rear , 5.0 / i_nb_channels ); + , 0 , -d_z , 1.5 / i_nb_channels ); i_next_atomic_operation += 2; i_source_channel_offset++; } - if ( i_physical_channels & AOUT_CHAN_MIDDLELEFT ) + if ( i_physical_channels & AOUT_CHAN_CENTER ) { + /* having two center channels increases the spatialization effect */ ComputeChannelOperations ( p_data , i_rate , i_next_atomic_operation , i_source_channel_offset - , -d_x , 0 , 1.5 / i_nb_channels ); + , d_x / 5.0 , d_z , 0.75 / i_nb_channels ); + i_next_atomic_operation += 2; + ComputeChannelOperations ( p_data , i_rate + , i_next_atomic_operation , i_source_channel_offset + , -d_x / 5.0 , d_z , 0.75 / i_nb_channels ); i_next_atomic_operation += 2; i_source_channel_offset++; } - if ( i_physical_channels & AOUT_CHAN_MIDDLERIGHT ) + if ( i_physical_channels & AOUT_CHAN_LFE ) { ComputeChannelOperations ( p_data , i_rate , i_next_atomic_operation , i_source_channel_offset - , d_x , 0 , 1.5 / i_nb_channels ); + , 0 , d_z_rear , 5.0 / i_nb_channels ); i_next_atomic_operation += 2; i_source_channel_offset++; } @@ -301,23 +310,54 @@ static int Init ( aout_filter_t * p_filter , struct aout_filter_sys_t * p_data static int Create( vlc_object_t *p_this ) { aout_filter_t * p_filter = (aout_filter_t *)p_this; + vlc_bool_t b_fit = VLC_TRUE; + + /* Activate this filter only with stereo devices */ + if ( p_filter->output.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) + || p_filter->output.i_physical_channels + != ( p_filter->output.i_original_channels & AOUT_CHAN_PHYSMASK ) + || p_filter->input.i_physical_channels + != ( p_filter->input.i_original_channels & AOUT_CHAN_PHYSMASK ) ) + { + msg_Dbg( p_filter, "Filter discarded (incompatible format)" ); + return VLC_EGENERIC; + } - if ( p_filter->output.i_physical_channels != ( AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT ) - || p_filter->input.i_format != p_filter->output.i_format - || p_filter->input.i_rate != p_filter->output.i_rate - || (p_filter->input.i_format != VLC_FOURCC('f','l','3','2') - && p_filter->input.i_format != VLC_FOURCC('f','i','3','2')) ) + /* Request a specific format if not already compatible */ + if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2') + || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { - msg_Dbg( p_filter, "Filter discarded (invalid format)" ); - return -1; + b_fit = VLC_FALSE; + p_filter->input.i_format = VLC_FOURCC('f','l','3','2'); + p_filter->output.i_format = VLC_FOURCC('f','l','3','2'); + } + if ( p_filter->input.i_rate != p_filter->output.i_rate ) + { + b_fit = VLC_FALSE; + p_filter->input.i_rate = p_filter->output.i_rate; + } + if ( p_filter->input.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) + && ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO ) ) + { + b_fit = VLC_FALSE; + p_filter->input.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | + AOUT_CHAN_CENTER | + AOUT_CHAN_REARLEFT | + AOUT_CHAN_REARRIGHT; + p_filter->input.i_original_channels = p_filter->input.i_physical_channels; + } + if ( ! b_fit ) + { + msg_Dbg( p_filter, "Requesting specific format" ); + return VLC_EGENERIC; } /* Allocate the memory needed to store the module's structure */ p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) ); if ( p_filter->p_sys == NULL ) { - msg_Err( p_filter, "out of memory" ); - return -1; + msg_Err( p_filter, "Out of memory" ); + return VLC_EGENERIC; } p_filter->p_sys->i_overflow_buffer_size = 0; p_filter->p_sys->p_overflow_buffer = NULL; @@ -329,13 +369,13 @@ static int Create( vlc_object_t *p_this ) , p_filter->input.i_physical_channels , p_filter->input.i_rate ) < 0 ) { - return -1; + return VLC_EGENERIC; } p_filter->pf_do_work = DoWork; p_filter->b_in_place = 0; - return 0; + return VLC_SUCCESS; } /***************************************************************************** diff --git a/modules/audio_filter/equalizer.c b/modules/audio_filter/equalizer.c index 0bfc27cb47..9d03e7dd9f 100644 --- a/modules/audio_filter/equalizer.c +++ b/modules/audio_filter/equalizer.c @@ -136,16 +136,26 @@ static int Open( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys; + vlc_bool_t b_fit = VLC_TRUE; if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { + b_fit = VLC_FALSE; + p_filter->input.i_format = VLC_FOURCC('f','l','3','2'); + p_filter->output.i_format = VLC_FOURCC('f','l','3','2'); msg_Warn( p_filter, "Bad input or output format" ); - return VLC_EGENERIC; } if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) { + b_fit = VLC_FALSE; + memcpy( &p_filter->output, &p_filter->input, + sizeof(audio_sample_format_t) ); msg_Warn( p_filter, "input and output formats are not similar" ); + } + + if ( ! b_fit ) + { return VLC_EGENERIC; } diff --git a/modules/audio_filter/normvol.c b/modules/audio_filter/normvol.c index 9dd60b25f4..98ddfe34ad 100644 --- a/modules/audio_filter/normvol.c +++ b/modules/audio_filter/normvol.c @@ -98,6 +98,7 @@ vlc_module_end(); static int Open( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t*)p_this; + vlc_bool_t b_fit = VLC_TRUE; int i_channels; aout_filter_sys_t *p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) ); @@ -105,13 +106,22 @@ static int Open( vlc_object_t *p_this ) if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { - msg_Warn( p_filter, "Bad input or output format" ); - return VLC_EGENERIC; + b_fit = VLC_FALSE; + p_filter->input.i_format = VLC_FOURCC('f','l','3','2'); + p_filter->output.i_format = VLC_FOURCC('f','l','3','2'); + msg_Warn( p_filter, "Bad input or output format" ); } if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) { + b_fit = VLC_FALSE; + memcpy( &p_filter->output, &p_filter->input, + sizeof(audio_sample_format_t) ); msg_Warn( p_filter, "input and output formats are not similar" ); + } + + if ( ! b_fit ) + { return VLC_EGENERIC; } diff --git a/modules/gui/macosx/extended.m b/modules/gui/macosx/extended.m index d25d216527..f502328c64 100644 --- a/modules/gui/macosx/extended.m +++ b/modules/gui/macosx/extended.m @@ -366,9 +366,9 @@ static VLCExtended *_o_sharedInstance = nil; /* en-/disable headphone virtualisation */ if ([o_ckb_hdphnVirt state] == NSOnState) { - [self changeAFiltersString: "headphone" onOrOff: VLC_TRUE ]; + [self changeAFiltersString: "headphone_channel_mixer" onOrOff: VLC_TRUE ]; }else{ - [self changeAFiltersString: "headphone" onOrOff: VLC_FALSE ]; + [self changeAFiltersString: "headphone_channel_mixer" onOrOff: VLC_FALSE ]; } } diff --git a/modules/gui/wxwidgets/extrapanel.cpp b/modules/gui/wxwidgets/extrapanel.cpp index 6dba73ba7b..84fb202c58 100644 --- a/modules/gui/wxwidgets/extrapanel.cpp +++ b/modules/gui/wxwidgets/extrapanel.cpp @@ -819,7 +819,7 @@ void ExtraPanel::OnHeadphone( wxCommandEvent &event ) { aout_instance_t *p_aout= (aout_instance_t *)vlc_object_find(p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE); - ChangeFiltersString( p_intf , p_aout, "headphone", + ChangeFiltersString( p_intf , p_aout, "headphone_channel_mixer", event.IsChecked() ? VLC_TRUE : VLC_FALSE ); if( p_aout != NULL ) vlc_object_release( p_aout ); diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c index 84be940c69..4948f6d3ea 100644 --- a/src/audio_output/filters.c +++ b/src/audio_output/filters.c @@ -116,36 +116,49 @@ static int SplitConversion( const audio_sample_format_t * p_input_format, return 2; } +static void ReleaseFilter( aout_filter_t * p_filter ) +{ + module_Unneed( p_filter, p_filter->p_module ); + vlc_object_detach( p_filter ); + vlc_object_destroy( p_filter ); +} + /***************************************************************************** * aout_FiltersCreatePipeline: create a filters pipeline to transform a sample * format to another ***************************************************************************** - * TODO : allow the user to add/remove specific filters + * pi_nb_filters must be initialized before calling this function *****************************************************************************/ int aout_FiltersCreatePipeline( aout_instance_t * p_aout, - aout_filter_t ** pp_filters, + aout_filter_t ** pp_filters_start, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ) { + aout_filter_t** pp_filters = pp_filters_start + *pi_nb_filters; audio_sample_format_t temp_format; int i_nb_conversions; if ( AOUT_FMTS_IDENTICAL( p_input_format, p_output_format ) ) { msg_Dbg( p_aout, "no need for any filter" ); - *pi_nb_filters = 0; return 0; } aout_FormatsPrint( p_aout, "filter(s)", p_input_format, p_output_format ); + if( *pi_nb_filters + 1 > AOUT_MAX_FILTERS ) + { + msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS ); + return -1; + } + /* Try to find a filter to do the whole conversion. */ pp_filters[0] = FindFilter( p_aout, p_input_format, p_output_format ); if ( pp_filters[0] != NULL ) { msg_Dbg( p_aout, "found a filter for the whole conversion" ); - *pi_nb_filters = 1; + ++*pi_nb_filters; return 0; } @@ -177,6 +190,12 @@ int aout_FiltersCreatePipeline( aout_instance_t * p_aout, /* We have the first stage of the conversion. Find a filter for * the rest. */ + if( *pi_nb_filters + 2 > AOUT_MAX_FILTERS ) + { + ReleaseFilter( pp_filters[0] ); + msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS ); + return -1; + } pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, p_output_format ); if ( pp_filters[1] == NULL ) @@ -186,10 +205,16 @@ int aout_FiltersCreatePipeline( aout_instance_t * p_aout, p_output_format, &temp_format ); if ( !i_nb_conversions ) { - vlc_object_detach( pp_filters[0] ); - vlc_object_destroy( pp_filters[0] ); + ReleaseFilter( pp_filters[0] ); msg_Err( p_aout, "couldn't find a filter for the second part of the conversion" ); + return -1; + } + if( *pi_nb_filters + 3 > AOUT_MAX_FILTERS ) + { + ReleaseFilter( pp_filters[0] ); + msg_Err( p_aout, "max filter reached (%d)", AOUT_MAX_FILTERS ); + return -1; } pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output, &temp_format ); @@ -198,31 +223,28 @@ int aout_FiltersCreatePipeline( aout_instance_t * p_aout, if ( pp_filters[1] == NULL || pp_filters[2] == NULL ) { - vlc_object_detach( pp_filters[0] ); - vlc_object_destroy( pp_filters[0] ); + ReleaseFilter( pp_filters[0] ); if ( pp_filters[1] != NULL ) { - vlc_object_detach( pp_filters[1] ); - vlc_object_destroy( pp_filters[1] ); + ReleaseFilter( pp_filters[1] ); } if ( pp_filters[2] != NULL ) { - vlc_object_detach( pp_filters[2] ); - vlc_object_destroy( pp_filters[2] ); + ReleaseFilter( pp_filters[2] ); } msg_Err( p_aout, "couldn't find filters for the second part of the conversion" ); + return -1; } - *pi_nb_filters = 3; + *pi_nb_filters += 3; + msg_Dbg( p_aout, "found 3 filters for the whole conversion" ); } else { - *pi_nb_filters = 2; + *pi_nb_filters += 2; + msg_Dbg( p_aout, "found 2 filters for the whole conversion" ); } - /* We have enough filters. */ - msg_Dbg( p_aout, "found %d filters for the whole conversion", - *pi_nb_filters ); return 0; } diff --git a/src/audio_output/input.c b/src/audio_output/input.c index 6c25a21819..a1e179f51a 100644 --- a/src/audio_output/input.c +++ b/src/audio_output/input.c @@ -37,66 +37,37 @@ #include "audio_output.h" #include "aout_internal.h" +static void inputFailure( aout_instance_t *, aout_input_t *, char * ); static int VisualizationCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); static int EqualizerCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); -static aout_filter_t * allocateUserChannelMixer( aout_instance_t *, - audio_sample_format_t *, - audio_sample_format_t * ); /***************************************************************************** * aout_InputNew : allocate a new input and rework the filter pipeline *****************************************************************************/ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) { - audio_sample_format_t user_filter_format; - audio_sample_format_t intermediate_format;/* input of resampler */ + audio_sample_format_t chain_input_format; + audio_sample_format_t chain_output_format; vlc_value_t val, text; char * psz_filters, *psz_visual; - aout_filter_t * p_user_channel_mixer; aout_FormatPrint( p_aout, "input", &p_input->input ); + p_input->i_nb_filters = 0; + /* Prepare FIFO. */ aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate ); p_input->p_first_byte_to_mix = NULL; /* Prepare format structure */ - memcpy( &intermediate_format, &p_aout->mixer.mixer, + memcpy( &chain_input_format, &p_input->input, sizeof(audio_sample_format_t) ); - intermediate_format.i_rate = p_input->input.i_rate; - - /* Try to use the channel mixer chosen by the user */ - memcpy ( &user_filter_format, &intermediate_format, - sizeof(audio_sample_format_t) ); - user_filter_format.i_physical_channels = p_input->input.i_physical_channels; - user_filter_format.i_original_channels = p_input->input.i_original_channels; - user_filter_format.i_bytes_per_frame = user_filter_format.i_bytes_per_frame - * aout_FormatNbChannels( &user_filter_format ) - / aout_FormatNbChannels( &intermediate_format ); - p_user_channel_mixer = allocateUserChannelMixer( p_aout, &user_filter_format, - &intermediate_format ); - /* If it failed, let the main pipeline do channel mixing */ - if ( ! p_user_channel_mixer ) - { - memcpy ( &user_filter_format, &intermediate_format, - sizeof(audio_sample_format_t) ); - } - - /* Create filters. */ - if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, - &p_input->i_nb_filters, - &p_input->input, - &user_filter_format - ) < 0 ) - { - msg_Err( p_aout, "couldn't set an input pipeline" ); - - aout_FifoDestroy( p_aout, &p_input->fifo ); - p_input->b_error = 1; - return -1; - } + memcpy( &chain_output_format, &p_aout->mixer.mixer, + sizeof(audio_sample_format_t) ); + chain_output_format.i_rate = p_input->input.i_rate; + aout_FormatPrepare( &chain_output_format ); /* Now add user filters */ if( var_Type( p_aout, "visual" ) == 0 ) @@ -198,13 +169,14 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) psz_filters = strdup( psz_visual ); } + /* parse user filter list */ if( psz_filters && *psz_filters ) { char *psz_parser = psz_filters; char *psz_next; while( psz_parser && *psz_parser ) { - aout_filter_t * p_filter; + aout_filter_t * p_filter = NULL; if( p_input->i_nb_filters >= AOUT_MAX_FILTERS ) { @@ -225,8 +197,6 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) break; } - msg_Dbg( p_aout, "user filter \"%s\"", psz_parser ); - /* Create a VLC object */ p_filter = vlc_object_create( p_aout, sizeof(aout_filter_t) ); if( p_filter == NULL ) @@ -238,33 +208,80 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) } vlc_object_attach( p_filter , p_aout ); - memcpy( &p_filter->input, &user_filter_format, + + /* request format */ + memcpy( &p_filter->input, &chain_input_format, sizeof(audio_sample_format_t) ); - memcpy( &p_filter->output, &user_filter_format, + memcpy( &p_filter->output, &chain_output_format, sizeof(audio_sample_format_t) ); - p_filter->p_module = - module_Need( p_filter,"audio filter", psz_parser, VLC_FALSE ); + /* try to find the requested filter */ + p_filter->p_module = module_Need( p_filter, "audio filter", + psz_parser, VLC_TRUE ); + + if ( p_filter->p_module == NULL ) + { + /* if the filter requested a special format, retry */ + if ( !( AOUT_FMTS_IDENTICAL( &p_filter->input, + &chain_input_format ) + && AOUT_FMTS_IDENTICAL( &p_filter->output, + &chain_output_format ) ) ) + { + aout_FormatPrepare( &p_filter->input ); + aout_FormatPrepare( &p_filter->output ); + p_filter->p_module = module_Need( p_filter, "audio filter", + psz_parser, VLC_TRUE ); + } + /* try visual filters */ + else + { + memcpy( &p_filter->input, &chain_output_format, + sizeof(audio_sample_format_t) ); + memcpy( &p_filter->output, &chain_output_format, + sizeof(audio_sample_format_t) ); + p_filter->p_module = module_Need( p_filter, "visualization", + psz_parser, VLC_TRUE ); + } + } + + /* failure */ + if ( p_filter->p_module == NULL ) + { + msg_Err( p_aout, "cannot add user filter %s (skipped)", + psz_parser ); + + vlc_object_detach( p_filter ); + vlc_object_destroy( p_filter ); + + psz_parser = psz_next; + continue; + } - if( p_filter->p_module== NULL ) + /* complete the filter chain if necessary */ + if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &p_filter->input ) ) { - p_filter->p_module = - module_Need( p_filter,"visualization", psz_parser, - VLC_FALSE ); - if( p_filter->p_module == NULL ) + if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, + &p_input->i_nb_filters, + &chain_input_format, + &p_filter->input ) < 0 ) { msg_Err( p_aout, "cannot add user filter %s (skipped)", psz_parser ); + module_Unneed( p_filter, p_filter->p_module ); vlc_object_detach( p_filter ); vlc_object_destroy( p_filter ); + psz_parser = psz_next; continue; } } - p_filter->b_continuity = VLC_FALSE; + /* success */ + p_filter->b_continuity = VLC_FALSE; p_input->pp_filters[p_input->i_nb_filters++] = p_filter; + memcpy( &chain_input_format, &p_filter->output, + sizeof( audio_sample_format_t ) ); /* next filter if any */ psz_parser = psz_next; @@ -273,60 +290,62 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) if( psz_filters ) free( psz_filters ); if( psz_visual ) free( psz_visual ); - /* Attach the user channel mixer */ - if ( p_user_channel_mixer ) + /* complete the filter chain if necessary */ + if ( !AOUT_FMTS_IDENTICAL( &chain_input_format, &chain_output_format ) ) { - p_input->pp_filters[p_input->i_nb_filters++] = p_user_channel_mixer; + if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters, + &p_input->i_nb_filters, + &chain_input_format, + &chain_output_format ) < 0 ) + { + inputFailure( p_aout, p_input, "couldn't set an input pipeline" ); + return -1; + } } /* Prepare hints for the buffer allocator. */ p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; p_input->input_alloc.i_bytes_per_sec = -1; + /* Create resamplers. */ if ( AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) ) { p_input->i_nb_resamplers = 0; } else { - /* Create resamplers. */ - intermediate_format.i_rate = (__MAX(p_input->input.i_rate, + chain_output_format.i_rate = (__MAX(p_input->input.i_rate, p_aout->mixer.mixer.i_rate) * (100 + AOUT_MAX_RESAMPLING)) / 100; - if ( intermediate_format.i_rate == p_aout->mixer.mixer.i_rate ) + if ( chain_output_format.i_rate == p_aout->mixer.mixer.i_rate ) { /* Just in case... */ - intermediate_format.i_rate++; + chain_output_format.i_rate++; } + p_input->i_nb_resamplers = 0; if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers, &p_input->i_nb_resamplers, - &intermediate_format, + &chain_output_format, &p_aout->mixer.mixer ) < 0 ) { - msg_Err( p_aout, "couldn't set a resampler pipeline" ); - - aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, - p_input->i_nb_filters ); - aout_FifoDestroy( p_aout, &p_input->fifo ); - var_Destroy( p_aout, "visual" ); - p_input->b_error = 1; - + inputFailure( p_aout, p_input, "couldn't set a resampler pipeline"); return -1; } aout_FiltersHintBuffers( p_aout, p_input->pp_resamplers, p_input->i_nb_resamplers, &p_input->input_alloc ); + p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; /* Setup the initial rate of the resampler */ p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; } p_input->i_resampling_type = AOUT_RESAMPLING_NONE; - p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; aout_FiltersHintBuffers( p_aout, p_input->pp_filters, p_input->i_nb_filters, &p_input->input_alloc ); + p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; /* i_bytes_per_sec is still == -1 if no filters */ p_input->input_alloc.i_bytes_per_sec = __MAX( @@ -334,9 +353,8 @@ int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input ) (int)(p_input->input.i_bytes_per_frame * p_input->input.i_rate / p_input->input.i_frame_length) ); - /* Allocate in the heap, it is more convenient for the decoder. */ - p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP; + /* Success */ p_input->b_error = VLC_FALSE; p_input->b_restart = VLC_FALSE; @@ -354,8 +372,10 @@ int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input ) aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, p_input->i_nb_filters ); + p_input->i_nb_filters = 0; aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers, p_input->i_nb_resamplers ); + p_input->i_nb_resamplers = 0; aout_FifoDestroy( p_aout, &p_input->fifo ); return 0; @@ -572,13 +592,38 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, return 0; } -static int ChangeFiltersString( aout_instance_t * p_aout, +/***************************************************************************** + * static functions + *****************************************************************************/ + +static void inputFailure( aout_instance_t * p_aout, aout_input_t * p_input, + char * psz_error_message ) +{ + /* error message */ + msg_Err( p_aout, "couldn't set an input pipeline" ); + + /* clean up */ + aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters, + p_input->i_nb_filters ); + aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers, + p_input->i_nb_resamplers ); + aout_FifoDestroy( p_aout, &p_input->fifo ); + var_Destroy( p_aout, "visual" ); + var_Destroy( p_aout, "equalizer" ); + var_Destroy( p_aout, "audio-filter" ); + var_Destroy( p_aout, "audio-visual" ); + + /* error flag */ + p_input->b_error = 1; +} + +static int ChangeFiltersString( aout_instance_t * p_aout, char* psz_variable, char *psz_name, vlc_bool_t b_add ) { vlc_value_t val; char *psz_parser; - var_Get( p_aout, "audio-filter", &val ); + var_Get( p_aout, psz_variable, &val ); if( !val.psz_string ) val.psz_string = strdup(""); @@ -613,7 +658,7 @@ static int ChangeFiltersString( aout_instance_t * p_aout, } } - var_Set( p_aout, "audio-filter", val ); + var_Set( p_aout, psz_variable, val ); free( val.psz_string ); return 1; } @@ -628,23 +673,23 @@ static int VisualizationCallback( vlc_object_t *p_this, char const *psz_cmd, if( !psz_mode || !*psz_mode ) { - ChangeFiltersString( p_aout, "goom", VLC_FALSE ); - ChangeFiltersString( p_aout, "visual", VLC_FALSE ); - ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_FALSE ); } else { if( !strcmp( "goom", psz_mode ) ) { - ChangeFiltersString( p_aout, "visual", VLC_FALSE ); - ChangeFiltersString( p_aout, "goom", VLC_TRUE ); - ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_TRUE ); + ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_FALSE); } else if( !strcmp( "galaktos", psz_mode ) ) { - ChangeFiltersString( p_aout, "visual", VLC_FALSE ); - ChangeFiltersString( p_aout, "goom", VLC_FALSE ); - ChangeFiltersString( p_aout, "galaktos", VLC_TRUE ); + ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_TRUE ); } else { @@ -652,9 +697,9 @@ static int VisualizationCallback( vlc_object_t *p_this, char const *psz_cmd, var_Create( p_aout, "effect-list", VLC_VAR_STRING ); var_Set( p_aout, "effect-list", val ); - ChangeFiltersString( p_aout, "goom", VLC_FALSE ); - ChangeFiltersString( p_aout, "visual", VLC_TRUE ); - ChangeFiltersString( p_aout, "galaktos", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "goom", VLC_FALSE ); + ChangeFiltersString( p_aout, "audio-visual", "visual", VLC_TRUE ); + ChangeFiltersString( p_aout, "audio-visual", "galaktos", VLC_FALSE); } } @@ -678,14 +723,16 @@ static int EqualizerCallback( vlc_object_t *p_this, char const *psz_cmd, if( !psz_mode || !*psz_mode ) { - i_ret = ChangeFiltersString( p_aout, "equalizer", VLC_FALSE ); + i_ret = ChangeFiltersString( p_aout, "audio-filter", "equalizer", + VLC_FALSE ); } else { val.psz_string = psz_mode; var_Create( p_aout, "equalizer-preset", VLC_VAR_STRING ); var_Set( p_aout, "equalizer-preset", val ); - i_ret = ChangeFiltersString( p_aout, "equalizer", VLC_TRUE ); + i_ret = ChangeFiltersString( p_aout, "audio-filter", "equalizer", + VLC_TRUE ); } @@ -700,48 +747,3 @@ static int EqualizerCallback( vlc_object_t *p_this, char const *psz_cmd, return VLC_SUCCESS; } - -static aout_filter_t * allocateUserChannelMixer( aout_instance_t * p_aout, - audio_sample_format_t * p_input_format, - audio_sample_format_t * p_output_format ) -{ - aout_filter_t * p_channel_mixer; - - /* Retreive user preferred channel mixer */ - char * psz_name = config_GetPsz( p_aout, "audio-channel-mixer" ); - - /* Not specified => let the main pipeline do the mixing */ - if ( ! psz_name ) return NULL; - - /* Debug information */ - aout_FormatsPrint( p_aout, "channel mixer", p_input_format, - p_output_format ); - - /* Create a VLC object */ - p_channel_mixer = vlc_object_create( p_aout, sizeof(aout_filter_t) ); - if( p_channel_mixer == NULL ) - { - msg_Err( p_aout, "cannot add user channel mixer %s", psz_name ); - return NULL; - } - vlc_object_attach( p_channel_mixer , p_aout ); - - /* Attach the suitable module */ - memcpy( &p_channel_mixer->input, p_input_format, - sizeof(audio_sample_format_t) ); - memcpy( &p_channel_mixer->output, p_output_format, - sizeof(audio_sample_format_t) ); - p_channel_mixer->p_module = - module_Need( p_channel_mixer,"audio filter", psz_name, VLC_TRUE ); - if( p_channel_mixer->p_module== NULL ) - { - msg_Err( p_aout, "cannot add user channel mixer %s", psz_name ); - vlc_object_detach( p_channel_mixer ); - vlc_object_destroy( p_channel_mixer ); - return NULL; - } - p_channel_mixer->b_continuity = VLC_FALSE; - - /* Ok */ - return p_channel_mixer; -} diff --git a/src/audio_output/output.c b/src/audio_output/output.c index c5106b3dd0..5cee853dc2 100644 --- a/src/audio_output/output.c +++ b/src/audio_output/output.c @@ -189,6 +189,7 @@ int aout_OutputNew( aout_instance_t * p_aout, aout_FormatPrint( p_aout, "mixer", &p_aout->output.output ); /* Create filters. */ + p_aout->output.i_nb_filters = 0; if ( aout_FiltersCreatePipeline( p_aout, p_aout->output.pp_filters, &p_aout->output.i_nb_filters, &p_aout->mixer.mixer, diff --git a/src/input/decoder.c b/src/input/decoder.c index 7589356e91..158515a13f 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -853,10 +853,30 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) if( p_sys->p_aout_input == NULL ) { + audio_sample_format_t format; + int i_force_dolby = config_GetInt( p_dec, "force-dolby-surround" ); + p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec; p_sys->audio = p_dec->fmt_out.audio; + + memcpy( &format, &p_sys->audio, sizeof( audio_sample_format_t ) ); + if ( i_force_dolby && (format.i_original_channels&AOUT_CHAN_PHYSMASK) + == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) ) + { + if ( i_force_dolby > 0 ) + { + format.i_original_channels = format.i_original_channels | + AOUT_CHAN_DOLBYSTEREO; + } + else + { + format.i_original_channels = format.i_original_channels & + ~AOUT_CHAN_DOLBYSTEREO; + } + } + p_sys->p_aout_input = - aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->audio ); + aout_DecNew( p_dec, &p_sys->p_aout, &format ); if( p_sys->p_aout_input == NULL ) { msg_Err( p_dec, "failed to create audio output" ); diff --git a/src/libvlc.h b/src/libvlc.h index 8bbfb85d65..c873f6d37d 100644 --- a/src/libvlc.h +++ b/src/libvlc.h @@ -159,6 +159,14 @@ static char *ppsz_snap_formats[] = "This option allows you to use the S/PDIF audio output by default when " \ "your hardware supports it as well as the audio stream being played.") +#define FORCE_DOLBY_TEXT N_("Force detection of Dolby Surround") +#define FORCE_DOLBY_LONGTEXT N_( \ + "Use this when you know your stream is or is not encoded with Dolby Surround " \ + "but fails to be detected as such." ) +static int pi_force_dolby_values[] = { 0, 1, -1 }; +static char *ppsz_force_dolby_descriptions[] = { N_("Auto"), N_("On"), N_("Off") }; + + #define AUDIO_FILTER_TEXT N_("Audio filters") #define AUDIO_FILTER_LONGTEXT N_( \ "This allows you to add audio post processing filters, to modify " \ @@ -169,12 +177,6 @@ static char *ppsz_snap_formats[] = "This allows you to add visualization modules " \ "(spectrum analyzer, etc.).") -#define AUDIO_CHANNEL_MIXER N_("Channel mixer") -#define AUDIO_CHANNEL_MIXER_LONGTEXT N_( \ - "This allows you to choose a specific audio channel mixer. For " \ - "instance, you can use the \"headphone\" mixer that gives 5.1 feeling " \ - "with a headphone.") - #define VOUT_CAT_LONGTEXT N_( \ "These options allow you to modify the behavior of the video output " \ "subsystem. You can for example enable video filters (deinterlacing, " \ @@ -960,6 +962,9 @@ vlc_module_begin(); AOUT_RESAMP_LONGTEXT, VLC_TRUE ); #endif add_bool( "spdif", 0, NULL, SPDIF_TEXT, SPDIF_LONGTEXT, VLC_FALSE ); + add_integer( "force-dolby-surround", 0, NULL, FORCE_DOLBY_TEXT, + FORCE_DOLBY_LONGTEXT, VLC_FALSE ); + change_integer_list( pi_force_dolby_values, ppsz_force_dolby_descriptions, 0 ); add_integer( "audio-desync", 0, NULL, DESYNC_TEXT, DESYNC_LONGTEXT, VLC_TRUE ); set_subcategory( SUBCAT_AUDIO_AOUT ); @@ -1239,8 +1244,6 @@ vlc_module_begin(); add_category_hint( N_("Miscellaneous"), MISC_CAT_LONGTEXT, VLC_TRUE ); add_module( "memcpy", "memcpy", NULL, NULL, MEMCPY_TEXT, MEMCPY_LONGTEXT, VLC_TRUE ); - add_module( "audio-channel-mixer", "audio mixer", NULL, NULL, - AUDIO_CHANNEL_MIXER, AUDIO_CHANNEL_MIXER_LONGTEXT, VLC_TRUE ); change_short('A'); set_section( N_("Plugins" ), NULL ); diff --git a/vlc.spec.mdk b/vlc.spec.mdk index 61a4672956..3ce9868893 100644 --- a/vlc.spec.mdk +++ b/vlc.spec.mdk @@ -808,6 +808,7 @@ rm -fr %buildroot %dir %_libdir/vlc/audio_filter %_libdir/vlc/audio_filter/libbandlimited_resampler_plugin.so +%_libdir/vlc/audio_filter/libdolby_surround_decoder_plugin.so %_libdir/vlc/audio_filter/libdtstospdif_plugin.so %_libdir/vlc/audio_filter/libfixed32tofloat32_plugin.so %_libdir/vlc/audio_filter/libfixed32tos16_plugin.so