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 #include "audio_output.h"
00032 #include "aout_internal.h"
00033
00034
00035
00036
00037 static int Create ( vlc_object_t * );
00038 static void Destroy ( vlc_object_t * );
00039
00040 static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
00041 aout_buffer_t * );
00042
00043
00044
00045
00046 vlc_module_begin();
00047 set_description( N_("Simple decoder for dolby surround encoded streams") );
00048 set_shortname( _("Dolby surround decoder") );
00049 set_category( CAT_INPUT );
00050 set_subcategory( SUBCAT_INPUT_ACODEC );
00051 set_capability( "audio filter", 5 );
00052 set_callbacks( Create, Destroy );
00053 vlc_module_end();
00054
00055
00056
00057
00058 struct aout_filter_sys_t
00059 {
00060 int i_left;
00061 int i_center;
00062 int i_right;
00063 int i_rear_left;
00064 int i_rear_center;
00065 int i_rear_right;
00066 };
00067
00068
00069 static const uint32_t pi_channels[] =
00070 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
00071 AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER,
00072 AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
00073
00074
00075
00076
00077 static int Create( vlc_object_t *p_this )
00078 {
00079 int i = 0;
00080 int i_offset = 0;
00081 aout_filter_t * p_filter = (aout_filter_t *)p_this;
00082
00083
00084 if ( p_filter->input.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
00085 || ! ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
00086 || aout_FormatNbChannels( &p_filter->output ) <= 2
00087 || ( p_filter->input.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO )
00088 != ( p_filter->output.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO ) )
00089 {
00090 return VLC_EGENERIC;
00091 }
00092
00093 if ( p_filter->input.i_rate != p_filter->output.i_rate )
00094 {
00095 return VLC_EGENERIC;
00096 }
00097
00098 if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
00099 || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
00100 {
00101 return VLC_EGENERIC;
00102 }
00103
00104
00105 p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
00106 if ( p_filter->p_sys == NULL )
00107 {
00108 msg_Err( p_filter, "Out of memory" );
00109 return VLC_EGENERIC;
00110 }
00111 p_filter->p_sys->i_left = -1;
00112 p_filter->p_sys->i_center = -1;
00113 p_filter->p_sys->i_right = -1;
00114 p_filter->p_sys->i_rear_left = -1;
00115 p_filter->p_sys->i_rear_center = -1;
00116 p_filter->p_sys->i_rear_right = -1;
00117
00118 while ( pi_channels[i] )
00119 {
00120 if ( p_filter->output.i_physical_channels & pi_channels[i] )
00121 {
00122 switch ( pi_channels[i] )
00123 {
00124 case AOUT_CHAN_LEFT:
00125 p_filter->p_sys->i_left = i_offset;
00126 break;
00127 case AOUT_CHAN_CENTER:
00128 p_filter->p_sys->i_center = i_offset;
00129 break;
00130 case AOUT_CHAN_RIGHT:
00131 p_filter->p_sys->i_right = i_offset;
00132 break;
00133 case AOUT_CHAN_REARLEFT:
00134 p_filter->p_sys->i_rear_left = i_offset;
00135 break;
00136 case AOUT_CHAN_REARCENTER:
00137 p_filter->p_sys->i_rear_center = i_offset;
00138 break;
00139 case AOUT_CHAN_REARRIGHT:
00140 p_filter->p_sys->i_rear_right = i_offset;
00141 break;
00142 }
00143 ++i_offset;
00144 }
00145 ++i;
00146 }
00147
00148 p_filter->pf_do_work = DoWork;
00149 p_filter->b_in_place = 0;
00150
00151 return VLC_SUCCESS;
00152 }
00153
00154
00155
00156
00157 static void Destroy( vlc_object_t *p_this )
00158 {
00159 aout_filter_t * p_filter = (aout_filter_t *)p_this;
00160
00161 if ( p_filter->p_sys != NULL )
00162 {
00163 free ( p_filter->p_sys );
00164 p_filter->p_sys = NULL;
00165 }
00166 }
00167
00168
00169
00170
00171 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
00172 aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
00173 {
00174 float * p_in = (float*) p_in_buf->p_buffer;
00175 float * p_out = (float*) p_out_buf->p_buffer;
00176 size_t i_nb_samples = p_in_buf->i_nb_samples;
00177 size_t i_nb_channels = aout_FormatNbChannels( &p_filter->output );
00178
00179 p_out_buf->i_nb_samples = i_nb_samples;
00180 p_out_buf->i_nb_bytes = sizeof(float) * i_nb_samples
00181 * aout_FormatNbChannels( &p_filter->output );
00182 memset ( p_out , 0 , p_out_buf->i_nb_bytes );
00183
00184 if ( p_filter->p_sys != NULL )
00185 {
00186 struct aout_filter_sys_t * p_sys = p_filter->p_sys;
00187 size_t i_nb_rear = 0;
00188 size_t i;
00189
00190 if ( p_sys->i_rear_left >= 0 )
00191 {
00192 ++i_nb_rear;
00193 }
00194 if ( p_sys->i_rear_center >= 0 )
00195 {
00196 ++i_nb_rear;
00197 }
00198 if ( p_sys->i_rear_right >= 0 )
00199 {
00200 ++i_nb_rear;
00201 }
00202
00203 for ( i = 0; i < i_nb_samples; ++i )
00204 {
00205 float f_left = p_in[ i * 2 ];
00206 float f_right = p_in[ i * 2 + 1 ];
00207 float f_rear = ( f_left - f_right ) / i_nb_rear;
00208
00209 if ( p_sys->i_center >= 0 )
00210 {
00211 float f_center = f_left + f_right;
00212 f_left -= f_center / 2;
00213 f_right -= f_center / 2;
00214
00215 p_out[ i * i_nb_channels + p_sys->i_center ] = f_center;
00216 }
00217
00218 if ( p_sys->i_left >= 0 )
00219 {
00220 p_out[ i * i_nb_channels + p_sys->i_left ] = f_left;
00221 }
00222 if ( p_sys->i_right >= 0 )
00223 {
00224 p_out[ i * i_nb_channels + p_sys->i_right ] = f_right;
00225 }
00226 if ( p_sys->i_rear_left >= 0 )
00227 {
00228 p_out[ i * i_nb_channels + p_sys->i_rear_left ] = f_rear;
00229 }
00230 if ( p_sys->i_rear_center >= 0 )
00231 {
00232 p_out[ i * i_nb_channels + p_sys->i_rear_center ] = f_rear;
00233 }
00234 if ( p_sys->i_rear_right >= 0 )
00235 {
00236 p_out[ i * i_nb_channels + p_sys->i_rear_right ] = f_rear;
00237 }
00238 }
00239 }
00240 }